EF modify entity in a function - asp.net-mvc

// Inside an action result
tp = dbContext.tp.Single(x => ...);
foreach (Sample sample in tp.samples)
{
if (sample.SampleStatusId == 1)
changeSamplestatus(sample, 2, now); //change samples to on hold
}
dbContext.SaveChanges();
public void changeSamplestatus(Sample sample, int sampleStatus, DateTime now)
{
sample.SampleHistory.Add(new SampleHistory
{
OldStatus = sample.SampleStatusId,
NewStatus = sampleStatus,
});
sample.SampleStatusId = sampleStatus;
}
I have an entity (sample) that I would like to change it status.
I am calling a function to do so, but the entity doesn't get modified (but it is creating a new row in history table with the correct FK).
It doesn't throw any errors when SaveChanges is called. It just doesn't modify the entity.

You can try:
//INSIDE AN ACTION RESULT
var tp = dbContext.tp.SingleOrDefault(x => ...);
if (tp != null)
{
foreach (Sample sample in tp.samples)
{
if (sample.SampleStatusId == 1)
changeSamplestatus(sample, 2, DateTime.Now);
}
int flag = dbContext.SaveChanges();
if (flag > 0)
{
// update successful
}
}
public void changeSamplestatus(Sample sample, int sampleStatus, DateTime now)
{
//sample.SampleHistory.Add(new SampleHistory
//{
// OldStatus = sample.SampleStatusId,
// NewStatus = sampleStatus,
//});
sample.SampleStatusId = sampleStatus;
}
Don't use Single for this case, because it would throw exception if no result was found or there were more than 1 result. Use SingleOrDefault or FirstOrDefault instead.

You can try this . I hope thiw will work . The Idea is to get the history records first in the context and then update the propterties and set state to mofifed . Please try I didnt tested it but it should work.
public void changeSamplestatus(Sample sample, int sampleStatus, DateTime now)
{
var historyRecordToUpdate = db.SampleHistory.FirstOrDefault(h=>h.id == sampleHistoryId )
if(historyRecordToUpdate !=null )
{
db.Entry(sample).State= EntityState.Modified;
sample.SampleStatusId = sampleStatus;
}
}

Related

Something is slow in my code, any suggestions?

I have a list of big records and I need to loop through each record, add some filter and calculation and add it to my another list. I think doing one by one is affecting the performance because it's taking like 12s to show 900 records.
I am unable to identify why it's taking too long. I used my chrome developer tool to identify where it's slow. Then I came to find out loading taking 0.2s, scripting taking 3s, rendering taking 3s, idle is 3s and others are two seconds.
Maybe I am using Entity Framework and DataTables is making it slow. Or maybe something wrong is with my query. Following is my code:
public ActionResult Index(int id, string language)
{
var All_Employees = from employee in db.Employees
.Include(x => x.Country).Include(x => x.Status)
where enployee.GenderId == id
select employee ;
var List = new List<EmployeeListViewModel>();
foreach(var Record in All_Employees.ToList()
.OrderByDescending(x=> ParseDate(x.JoiningDate)))
{
EmployeeListViewModel item = new EmployeeListViewModel();
item.Id = Record.Id;
item.Code = Record.Code;
if(Record.CountryId != null)
{
if(language == "en")
{
item.Country = Record.Country.NameE;
}
else
{
item.Country = Record.Country.NameA;
}
}
item.Date = Record.JoiningDate;
int WorkingDays = 0;
if(Record.JoiningDate != null)
{
DateTime Joining= Convert.ToDateTime(ParseDate(Record.Record.JoiningDate));
TimeSpan t = DateTime.Now.Date - Joining;
int Days = int.Parse(t.TotalDays.ToString());
if (Days > 0)
{
WorkingDays = Days;
}
}
item.Days = WorkingDays.ToString();
if (Record.StatusId != null)
{
if (language == "en")
{
item.Status = Record.Status.NameE;
}
else
{
item.Status = Record.Status.NameE;
}
}
List.Add(item);
}
return View(List);
}
Another reason could be I am converting my date:
private static DateTime? ParseDate(string dateString)
{
if(dateString != null)
{
return DateTime.ParseExact(dateString, "dd-MM-yyyy", CultureInfo.GetCultureInfo("en-US"), DateTimeStyles.None);
}
else
{
return null;
}
}
I don't want to make date filed as DateTime in my database, due to some reasons.
What's the best way to improve performance in my current situation?
Too much casting is used here in your code and list is created twice. One way you can do code like below.
List<EmployeeListViewModel> lstData = EmployeeListViewModel.ToList();
for(int i = 0; i < lstData.Count; i++)
{
//Put logic here for required changes like Language and Date.
if(lstData[i].CountryId != null)
{
if(language == "en")
lstData[i].Country = lstData[i].Country.NameE;
else
lstData[i].Country = lstData[i].Country.NameA;
}
}
Try to reduce casting specially for string and date-time. Below is example.
int Days = int.Parse(t.TotalDays.ToString());
In above line t.TotalDays is always int type, no need to cast to string and int again.

How can I handle error as Value cannot be null. Parameter name: source

My below view code in View is below
#{
ViewBag.Title = "Student Dashboard";
var StudentRequestTimedt = ViewBag.StudentRequestTime as DataTable;
if (StudentRequestTimedt != null)
{
var StudentRequestTime = StudentRequestTimedt.AsEnumerable().Select(t => new
{
StudentRequestId = t.Field<int>("StudentRequestId"),
FromTime = t.Field<string>("FromTime"),
ToTime = t.Field<string>("ToTime"),
}).ToList();
}
else
{ var StudentRequestTime = ""; }
}
if (StudentRequestTime != "")
{
var StudentRequestTimecount = StudentRequestTime.Where(d => d.StudentRequestId == StudentRequestId).ToList();
}
On writting this I am getting error as StudentRequestTime doesnot exist in the current context.
This issue comes in case I am returning ViewBag.StudentRequestTime as null from controller side
My controller side code is as
if (GetData.Tables[1].Rows.Count > 0 && GetData.Tables[0].Rows.Count > 0)
{
ViewBag.StudentRequestTime = GetData.Tables[1];
}
else
{
ViewBag.StudentRequestTime = null;
}
return View();
Please Also review this below image, Here I am getting data in multiple viewbag in this case how can I manage? var StudentRequestTime is null or empty
How can I handle this issue ?
Updated code resolved my issue
Old code of controller
if (GetData.Tables[1].Rows.Count > 0 && GetData.Tables[0].Rows.Count > 0)
{
ViewBag.StudentRequestTime = GetData.Tables[1];
}
else
{
ViewBag.StudentRequestTime = null;
}
return View();
New Code of controller
ViewBag.StudentRequestTime = GetData.Tables[1];
On ViewSide
Consider this example:
if (eyeColor == EyeColor.Green)
{
// greenEyeColorFound has been declared *in this if statement*,
// so it only exists *within this if statement*
var greenEyeColorFound = true;
}
// this will fail. greenEyeColorFound was declared *in the first if statement*,
// how can the if statement below be aware of it's existence?
if (greenEyeColorFound == true)
{
Debug.WriteLine("Found a person with green eyes!");
}
greenEyeColorFound is locally scoped to the first if statement. Only code within that if statement can be aware of it's existence.
To get my example to work, greenEyeColorFound should be accessible by both ifs, which can be achieved by placing it's declaration outside of both ifs:
// this is now declared *outside* of the two if statements,
// so both are now aware of it and can access it's value.
var greenEyeColorFound = false;
if (eyeColor == EyeColor.Green)
{
greenEyeColorFound = true;
}
// presto, this now works
if (greenEyeColorFound == true)
{
Debug.WriteLine("Found a person with green eyes!");
}
This is the exact issue you are having with StudentRequestTime. Declare it once outside of the ifs, then just set it's value in your if/else statements.
Since we're at it, I wouldn't use ViewBag at all, let alone have it carry DataTables over to the Razor side. I would use viewmodels (read "Accessing Your Model's Data from a Controller" over at Microsoft ASP.NET MVC docs to see how this works, in particular section "Strongly Typed Models and the #model Keyword") which are much cleaner and maintainable.
You can easily refactor your existing code to use viewmodels using the steps below:
1) Create a class, let's name it StudentRequestTimeViewModel:
public class StudentRequestTimeViewModel
{
public int StudentRequestId { get; set; }
public string FromTime { get; set; }
public string ToTime { get; set; }
}
2) In your controller, populate a List<StudentRequestTimeViewModel>:
var studentRequestTimes = new List<StudentRequestTimeViewModel>();
if (GetData.Tables[1].Rows.Count > 0 && GetData.Tables[0].Rows.Count > 0)
{
// populate studentRequestTimes here
}
// return the view, passing in studentRequestTimes as our model
return View(studentRequestTimes);
3) Your Razor then becomes:
/* your model is declared as "#model",
but is accessed as "Model". */
#model List<StudentRequestTimeViewModel>
#if (Model != null && Model.Count > 0)
{
/* your List<StudentRequestTimeViewModel> Model is not null or empty */
foreach(var studentRequestTime in Model)
{
<p>Student with ID #studentRequestTime.StudentRequestId is here.</p>
}
}
else
{
/* your List<StudentRequestTimeViewModel> Model is null or empty */
}

'System.Linq.IQueryable<NewsSite.Models.Domain.Tbl_News>' does not contain a definition

I Create A News Site With MVC5 But I Have Problem .
in Model i Create A Repository Folder And in this i Create Rep_Setting for
Connect to Tbl_Setting in DataBase .
public class Rep_Setting
{
DataBase db = new DataBase();
public Tbl_Setting Tools()
{
try
{
var qGetSetting = (from a in db.Tbl_Setting
select a).FirstOrDefault();
return qGetSetting;
}
catch (Exception)
{
return null;
}
}
}
And i Create a Rep_News for Main Page .
DataBase db = new DataBase();
Rep_Setting RSetting = new Rep_Setting();
public List<Tbl_News> GetNews()
{
try
{
List<Tbl_News> qGetNews = (from a in db.Tbl_News
where a.Type.Equals("News")
select a).OrderByDescending(s => s.ID).Skip(0).Take(RSetting.Tools().CountNewsInPage).ToList();
return qGetNews;
}
catch (Exception ex)
{
return null;
}
}
But This Code Have Error to Me
OrderByDescending(s=>s.ID).Skip(0).Take(RSetting.Tools().CountNewsInPage).ToList();
Error :
Error 18 'System.Linq.IQueryable<NewsSite.Models.Domain.Tbl_News>' does
not contain a definition for 'Take' and the best extension method overload
'System.Linq.Queryable.Take<TSource>(System.Linq.IQueryable<TSource>, int)' has
some invalid arguments
E:\MyProject\NewsSite\NewsSite\Models\Repository\Rep_News.cs 50 52 NewsSite
How i Resolve it ?
Try it this way. The plan of debugging is to split your execution, this also makes for a more reusable method in many cases. And a good idea is to avoid using null and nullables if you can, if you use them "on purpose" the you must have a plan for them.
DataBase db = new DataBase();
Rep_Setting RSetting = new Rep_Setting();
public List<Tbl_News> GetNews()
{
int skip = 0;
Tbl_Setting tools = RSetting.Tools();
if(tools == null){ throw new Exception("Found no rows in the database table Tbl_Setting"); }
int? take = tools.CountNewsInPage;//Nullable
if(!take.HasValue)
{
// Do you want to do something if its null maybe set it to 0 and not null
take = 0;
}
string typeStr = "News";
List<Tbl_News> qGetNews = (from a in db.Tbl_News
where a.Type.Equals(typeStr)
select a).OrderByDescending(s => s.ID).Skip(skip).Take(take.Value);
return qGetNews.ToList();
}
if qGetNews is a empty list you now don't break everything after trying to iterate on it, like your return null would. instead if returning null for a lit return a new List<>() instead, gives you a more resilient result.
So I said reusable method, its more like a single action. So you work it around to this. Now you have something really reusable.
public List<Tbl_News> GetNews(string typeStr, int take, int skip = 0)
{
List<Tbl_News> qGetNews = (from a in db.Tbl_News
where a.Type.Equals(typeStr)
select a).OrderByDescending(s => s.ID).Skip(skip).Take(take);
return qGetNews.ToList();
}
Infact you shjould always try to avoid returning null if you can.
public class Rep_Setting
{
DataBase db = new DataBase();
public Tbl_Setting Tools()
{
var qGetSetting = (from a in db.Tbl_Setting
select a).FirstOrDefault();
if(qGetSetting == null){ throw new Exception("Found no rows in the database table Tbl_Setting"); }
return qGetSetting;
}
}

Reflection + Entity Framework to update data in MVC app

I've got a complex form on a page that is bound to a POCO representing a rather complex entity. One of the requirements is that, on blur, I update the database.
I'm currently passing the property (as key), value, and CampaignId via ajax. The key might look something like: Campaign.FanSettings.SocialSharing.FacebookLinkText.
I am using the code below, and getting "close". My final propertyToSet is the FacebookLinkText is not being set, because my object source is of type Entities.Campaign, while my object value is simply a string. I understand these need to be the same type, but I don't understand how to do that. Two questions:
How do I modify the code below to be able to execute the propertyToSet.SetValue method
Since I'm casting this to an object, I don't see how this would actually update my entity, so when I call SaveChanges it updates appropriately. What am I missing?
Thanks!
Code:
public void UpdateCampaign(int id, string key, string value)
{
using (var context = new BetaEntities())
{
var camp = context.Campaigns.Where(e => e.Id == id).Single();
SetProperty(camp, key,value);
}
}
public void SetProperty(object source, string property, object value)
{
string[] bits = property.Split('.');
for (int i = 0; i < bits.Length - 1; i++)
{
PropertyInfo prop = source.GetType().GetProperty(bits[i]);
source = prop.GetValue(source, null);
}
PropertyInfo propertyToSet = null;
if (source is IEnumerable)
{
foreach (object o in (source as IEnumerable))
{
propertyToSet = o.GetType().GetProperty(bits[bits.Length - 1]);
break;
}
}
else
{
propertyToSet = source.GetType().GetProperty(bits[bits.Length - 1]);
}
propertyToSet.SetValue(source, value, null);
}
Solved.
public void UpdateCampaign(int id, string key, string value)
{
using (var context = new BetaEntities())
{
var camp = context.Campaigns.Where(e => e.Id == id).Single();
SetProperty(camp, key, value);
context.SaveChanges()
}
}
public void SetProperty(object source, string property, object value)
{
string[] bits = property.Split('.');
for (int i = 0; i < bits.Length - 1; i++)
{
PropertyInfo prop = source.GetType().GetProperty(bits[i]);
source = prop.GetValue(source, null);
}
PropertyInfo propertyToSet = null;
if (source is IEnumerable)
{
foreach (object o in (source as IEnumerable))
{
propertyToSet = o.GetType().GetProperty(bits[bits.Length - 1]);
propertyToSet.SetValue(o, value,null);
break;
}
}
else
{
propertyToSet = source.GetType().GetProperty(bits[bits.Length - 1]);
propertyToSet.SetValue(source, value, null);
}
}

ASP .NET MVC with ADO .NET causing issues?

I'm new to both ADO .NET and MVC, and I am trying to do something simple where I am editting a "DailyReport", which is basically representing a work-report.
Here's my relevant controller pattern:
//
// GET: /DailyReport/Edit/5
public ActionResult Edit(int id, int weeklyReportID, int day)
{
WeeklyReport weeklyReport = (
from WeeklyReport wr in db.WeeklyReports
where wr.Id == weeklyReportID select wr)
.FirstOrDefault();
ViewBag.Week = weeklyReport.Week;
ViewBag.Day = day;
return View();
}
//
// POST: /DailyReport/Edit/5
[HttpPost]
public ActionResult Edit(DailyReport dailyReport, int weeklyReportID, int day)
{
if (ModelState.IsValid)
{
db.SaveChanges();
if (dailyReport == null)
{
dailyReport = new DailyReport();
dailyReport.StartTime = new TimeSpan(7, 0, 0);
dailyReport.EndTime = new TimeSpan(7 + 8, 0, 0);
dailyReport.Day = day;
db.DailyReports.AddObject(dailyReport);
db.SaveChanges();
}
WeeklyReport weeklyReport = (
from WeeklyReport wr in db.WeeklyReports
where wr.Id == weeklyReportID select wr)
.FirstOrDefault();
if (!weeklyReport.DailyReport.Any(dr => dr.Id == dailyReport.Id))
{
weeklyReport.DailyReport.Add(dailyReport);
}
dailyReport.WeeklyReport = weeklyReport;
db.SaveChanges();
return RedirectToAction("Edit",
"WeeklyReport",
new {
id = weeklyReportID,
week = weeklyReport.Week,
year = weeklyReport.Year
});
}
return View(dailyReport);
}
When I am editting the datetime value, it doesn't get saved. In the HttpPost section when I debug it, the object is indeed changed to reflect these changes, but calling db.SaveChanges() doesn't commit it to the database.
Edit "db" in this case is my ADO .NET context, declared in the following way:
ActivesEntities db = new ActivesEntities();
ActivesEntities has this declaration:
public partial class ActivesEntities : ObjectContext { ... }
First of all, I would recommend you to not call the db.SaveChanges until you really need to save an Entity object in the middle of the series of Transactional Steps..
Because Entity Framework support saving all the EntityContext object in a single shot !
And I think you may try changing the code like this,
[HttpPost]
public ActionResult Edit(DailyReport dailyReport, int weeklyReportID, int day)
{
if (ModelState.IsValid)
{
if (dailyReport == null)
{
dailyReport = new DailyReport();
dailyReport.StartTime = new TimeSpan(7, 0, 0);
dailyReport.EndTime = new TimeSpan(7 + 8, 0, 0);
dailyReport.Day = day;
db.DailyReports.AddObject(dailyReport);
}
WeeklyReport weeklyReport = (from WeeklyReport wr in db.WeeklyReports where wr.Id == weeklyReportID select wr).SingleOrDefault();
if (!weeklyReport.DailyReport.Any(dr => dr.Id == dailyReport.Id))
{
weeklyReport.DailyReport.Add(dailyReport);
}
dailyReport.WeeklyReport = weeklyReport;
db.SaveChanges();
return RedirectToAction("Edit", "WeeklyReport", new { id = weeklyReportID, week = weeklyReport.Week, year = weeklyReport.Year });
}
I think using if you are Updating the entity object then you need to call SingleOrDefault and not FirstOrDefault. I do it like this on Linq2Sql..
you are using entity framework right? it's a bit different from ADO.NET (it uses it but those are not 100% same thing), we should add the tag EF to the question.
said so, why do you call db.SaveChanges twice? I would not call it at the top of your Edit method.
also, as I see in some EF examples, you can use Add and not AddObject.
check this one:
How to: Add, Modify, and Delete Objects
last thing, your StartTime and EndTime properties of the object are of type TimeSpan and not datetime?

Resources