.net MVC entity framework SaveChanges does not working - c#

I want to update my db like
var context = new asb_cardEntities3();
var query = db.WFileMaster.Where(q => q.ID ==
data.ID).FirstOrDefault();
query.SUBE = item.SUBE.ToString();
query.HES_NO = item.HES_NO.ToString();
query.DVZ_KOD = item.DVZ_KOD.ToString();
query.TUTAR = item.TUTAR.ToString();
//context.Entry(query).State = SUBE.Modified;
context.SaveChanges();
this, I did not get any error (all data come) I am new in this framework, I think problem is in context. But I did not find any solution.

Please change db to context while retrieving the record in the second line.
var context = new asb_cardEntities3();
var query = context.WFileMaster.Where(q => q.ID == data.ID).FirstOrDefault();
query.SUBE = item.SUBE.ToString();
query.HES_NO = item.HES_NO.ToString();
query.DVZ_KOD = item.DVZ_KOD.ToString();
query.TUTAR = item.TUTAR.ToString();
context.SaveChanges();

Before saving changes update the table
something like that
.Update(x => x.Id== ID, object); and then
save changes.

Related

Linq replace column value with another value

Well, im doing a linq query to get a list of results with the same column, and then i need to replace that column value with a new one.
First Code:
var db = GetContext();
var result = from f in GetContext().ProjectStateHistories
where f.ProjectId.Equals(oldProjectId)
select f;
foreach (var item in result)
{
var projectStateHistoryUpdate = db.ProjectStateHistories.Find(item.Id);
projectStateHistoryUpdate.ProjectId = newProjectId;
db.Entry(projectStateHistoryUpdate).State = EntityState.Modified;
}
db.SaveChanges();
I searched for some answers, and i found that i can use Select, and make a new object (Linq replace null/empty value with another value)
Second Code:
var result = (from f in GetContext().ProjectStateHistories
where f.ProjectId.Equals(oldProjectId)
select f).Select(d=> new { Id = d.Id, EventName = d.EventName, LogUser = d.LogUser, ProjectId = newProjectId, TimeStamp = d.TimeStamp });
And even, Third Code:
var db = GetContext();
var result = (from f in db.ProjectStateHistories
where f.ProjectId.Equals(oldProjectId)
select f).Select(d=> new { ProjectId = newProjectId});
But only the First Code works.
I wanted to ask what i am doing wrong, since i think it is better to change the value with a query, instead of using a foreach.
See code below:
var db = GetContext();
(from f in db.ProjectStateHistories
where f.ProjectId.Equals(oldProjectId)
select f)
.ToList()
.ForEach(i => i.ProjectId = newProjectId);
db.SaveChanges();
Alternatively:
var db = GetContext();
db.ProjectStateHistories
.Where(f => f.ProjectId.Equals(oldProjectId))
.ToList()
.ForEach(f => f.ProjectId = newProjectId);
db.SaveChanges();
The shortest way I know of to replace your code is this:
var db = getcontext();
db.ProjectStateHistories
.Where(f => f.ProjectId.Equals(oldProjectId))
.ToList()
.ForEach(f => f.ProjectId = newProjectId);
db.SaveChanges();
Other answers can be found here
I've just had a thought that could help you, I am just free coding here!
If you just put the for each as part of the select, and then save your changes will that work?
foreach (var source in db.ProjectStateHistories.Where(x => x.ProjectId == oldProjectId))
{
source.ProjectId= newProjectId;
db.Entry(source).State = EntityState.Modified;
}
db.SaveChanges();
I think this is a more efficient way of doing it.
Also the .Select() method is only really useful if you need to Project to a view Model, it won't change the variables in the database, just show them in the newly declared object.
Thanks,
Phill

EF6 cascade object very slow to setup

I have a problem with entity framework, when trying to retreive data.
I split the work into multiple steps:
generate the query
Execute it and retreive dataset from db.
Fill in my ViewModel using dataset.
Actualy, step 1 and 2 are very fast, step 3 can take up to 1 minute (for 200 records). Meaning it's not SQL related (i copied query from debugger to MSSMS, and it's executed in less than a second).
First i was using step 3B, to make it simple, i retreive a Job entity which i transform into a MapMarker object. and i thaught it was the ConvertAll that was slowing down the process.
After some SO reading, I tested using Select but result was the same.
The only this is, if i use the "main object", in this example: Job, everything is fast; as a test, i put the Job.Job_ID into all field, and the execution time is normal (less than a second).
Then i insert again this: ,Latitude = _Job.Maintenance.Equipement.Location.GPS.GPS_Latitude.Value and the slowlyness is back.
I even tried step 3C using a foreach loop (which i knew was not better but ok...) but it is as slow as other solutions.
The main question is:
What am i missing in the EF6 configuration (or somewhere else ?) that make this process so slow ?
I'm going to do it the good old way and execute my own sql query, i started using EF, i guess these entities should be usable, for now using "simple" objects works realy fine but if you cannot cascade them.. what is the added value ?
Below the steps i'm talking about.
Step 1:
IEnumerable<Job> Jobs = db.Job.Include(e => e.Maintenance.MaintenancePlan.MaintenanceType).Include(e => e.Maintenance.MaintenancePlan.MaintenanceType)
.Include(e => e.Maintenance.MaintenancePlan.MaintenanceType.Shape)
.Include(e => e.Maintenance.MaintenanceStatus)
.Include(e => e.Users)
.Include(e => e.Users.Color)
.Include(e => e.Maintenance.Equipement.Location.GPS);
Step 2:
List<Job> listJobs = Jobs.ToList();
Step 3A:
IEnumerable<MapMarker> IEMarkerJobsA = Jobs.AsEnumerable().Select(_Job => new MapMarker
{
ID = string.Format("Job_{0}", _Job.Job_ID)
,Latitude = _Job.Maintenance.Equipement.Location.GPS.GPS_Latitude.Value
,Longitude = _Job.Maintenance.Equipement.Location.GPS.GPS_Longitude.Value
});
List<MapMarker> listMarkerJobsA = IEMarkerJobsA.ToList();
Step 3B:
IEnumerable listMarkerJobs = listJobs.ConvertAll(
new Converter(MapMarker.MapMarkerFactory));
When the Factory is like this:
public static MapMarker MapMarkerFactory(Job _Job)
{
MapMarker A = new MapMarker();
A.ID = String.Format("Job_{0}", _Job.Job_ID);
A.Latitude = _Job.Maintenance.Equipement.Location.GPS.GPS_Latitude.Value;
A.Longitude = _Job.Maintenance.Equipement.Location.GPS.GPS_Longitude.Value;
A.Title = String.Format("{1}", (_Job.Users != null) ? String.Format("[{0}]", _Job.Users.Users_NickName) : "", _Job.Maintenance.Equipement.Equipement_Name);
A.Icon = GetIconePath((_Job.Users != null) ? _Job.Users.Color.Color_Name : "red", _Job.Maintenance.MaintenancePlan.MaintenanceType.Shape.Shape_Name, _Job.Maintenance.MaintenanceStatus.MaintenanceStatus_Description, "13px");
A.IconSize = new Size(13, 13);
A.WindowInfoContent = String.Format("JobID= {0}", _Job.Job_ID);
return A;
}
Step 3C:
List<MapMarker> listMarkerJobs = new List<MapMarker>();
foreach (Job _Job in Jobs)
{
MapMarker A = new MapMarker();
A.ID = String.Format("Job_{0}", _Job.Job_ID);
A.Latitude = _Job.Maintenance.Equipement.Location.GPS.GPS_Latitude.Value:
A.Longitude = _Job.Maintenance.Equipement.Location.GPS.GPS_Longitude.Value;
A.Title = String.Format("{1}", (_Job.Users != null) ? String.Format("[{0}]", _Job.Users.Users_NickName) : "", _Job.Maintenance.Equipement.Equipement_Name);
A.Icon = MapMarker.GetIconePath((_Job.Users != null) ? _Job.Users.Color.Color_Name : "red", _Job.Maintenance.MaintenancePlan.MaintenanceType.Shape.Shape_Name, _Job.Maintenance.MaintenanceStatus.MaintenanceStatus_Description, "13px");
A.IconSize = new System.Drawing.Size(13, 13);
A.WindowInfoContent = String.Format("JobID= {0}", _Job.Job_ID);
listMarkerJobs.Add(A);
}
Try this for part 3
List<MapMarker> listMarkerJobs = Jobs.AsNoTracking().Select(_Job => new MapMarker
{
ID = string.Format("Job_{0}", _Job.Job_ID),
Latitude = _Job.Maintenance.Equipement.Location.GPS.GPS_Latitude.Value,
Longitude = _Job.Maintenance.Equipement.Location.GPS.GPS_Longitude.Value
}).ToList();

Entity framework `AsNoTracking` is not working with anonymous projection

In the below snipped i try to fetch data using Anonymous Projection and i would like do not track the entities that is fetched.
Note : i have already gone through existing stack question,yet unable to find a working solution for me
using (var db = new Entities())
{
db.Configuration.LazyLoadingEnabled = false;
db.Configuration.ProxyCreationEnabled = false;
var myprojection = db.Table1
.AsNoTracking()
.Include(gh=>gh.Table2) //Update
.Include(gh=>gh.Table3) //Update
.Select(x => new
{
table1= x,
table2= x.Table2.Where(g => Some Condition),
table3= x.Table3.Where(g=>Some Condition)
})
.ToList();
var result = myprojection.Select(g =>g.table1).FirstOrDefault();
}
When i useAsNoTracking() data from the inner tables (table2,3) is lost during the conversion at this line var result = myprojection.Select(g =>g.table1).FirstOrDefault();
Edit
If i remove AsNoTracking() everything works fine.
1) How to use projection and AsNoTracking in entity framework correctly ?
2) Any other option to remove tracking of this query?
Is there any possible workarounds?
Use ToList() for your navigation properties. Note that it will still projekt in the DB. (EF6)
// ..
table2 = x.Table2.Where(g => Some Condition).ToList(),
Update:
With EF4 you probably need to map table2 manually:
table2 = x.Table2.Where(g => CONDITION).Select(x => new {Foo = x.Bar}),
When i useAsNoTracking() data from the inner tables (table2,3) is lost during the conversion at this line var result = myprojection.Select(g =>g.table1).FirstOrDefault();
Your selecting Table1, into an anonymous type you will not have access to table2 or table3 although the navigation properties are they they will not map. Entities loses it relationships when you select into anonymous type you need to select table two and three or don't pull it into an anonymous type.
Just put your wheres directly in the table one where and then make your call
var myprojection = db.Table1.Join(db.Table2.Where(x => yourcondition),
t1 => t1.id, t2 => t2.t1id, (t1, t2) => t1 );
then you have to do another join for table3
but your probably better just making the call in two queries
First of all, it does not make sense to use
db.Configuration.ProxyCreationEnabled = false and AsNoTracking()
at the same time.
If you use db.Configuration.ProxyCreationEnabled = false change tracking will turn off for all queries.
But your problem with inner tables 2 and 3 is not caused by AsNoTracking().
db.Configuration.LazyLoadingEnabled = false;
db.Configuration.ProxyCreationEnabled = false;
Turn off lazy loading and i guess it's good for performance reason. If turn it on, you will get expected result, but Entity Framework will make additional SQL query to Data Base for every row in myprojection result. You should better do the following:
using (var db = new Entities())
{
db.Configuration.LazyLoadingEnabled = false;
db.Configuration.ProxyCreationEnabled = false;
var myprojection = db.Table1
.Include(x=>x.Table2).Include(x=>x.Table3)
.Select(x => new
{
table1= x,
table2= x.Table2.Where(g => Some Condition),
table3= x.Table3.Where(g=>Some Condition)
})
.ToList();
var result = myprojection.Select(g =>g.table1).FirstOrDefault();
}
Using .Include(x=>x.Table2).Include(x=>x.Table3) in your query will
force Entity Framerwork to load related Table2 and Table3 for one
query to Data Base.
Maybe you can try like this:
using (var db = new Entities())
{
db.Configuration.LazyLoadingEnabled = false;
db.Configuration.ProxyCreationEnabled = false;
var myprojection = db.Table1
//.AsNoTracking() //remove.AsNoTracking() from here
.Select(x => new
{
table1= x,
table2= x.Table2.Where(g => Some Condition),
table3= x.Table3.Where(g=>Some Condition)
})
.AsNoTracking()//add .AsNoTracking() here
.ToList();
var result = myprojection.Select(g =>g.table1).FirstOrDefault();
}
NOTE: I dont try this. Just an idea, i hope this helps to you

Role description does not get updated

I am getting the role being created but the description does not get updated.
I have tried in two ways:
First:
Roles.CreateRole(model.RoleName);
using (tgpwebgedEntities context = new tgpwebgedEntities())
{
var query = from r in context.aspnet_Roles where r.RoleName == r.RoleName select r;
var obj = query.First();
obj.Description = model.Description;
context.SaveChanges();
}
Second:
using(tgpwebgedEntities context = new tgpwebgedEntities()) {
var obj = context.aspnet_Roles.Single(r => r.RoleName == roleModel.RoleName);
obj.Description = roleModel.Description;
context.SaveChanges();
}
The curious thing is that this second way is the way I am using when the user is editing an aready created role using another action and works fine.
This first is used in a method that created the role and update its description since there is no support for description in .NET.
The problem is with your query statement,
var query = from r in context.aspnet_Roles where r.RoleName == r.RoleName select r;
"r.RoleName == r.RoleName" which will always be true and returns all entries. The query should be something similar to what you have in the second query
r => r.RoleName == roleModel.RoleName

How do I attach and update an existing entity?

I want to construct a disconnected object on my web page:
var entity = new MyEntity();
entity.ID = IdFromPage;
entity.Name = UpdatedNameFromPage;
Connect it to my object context and then call context.Save()
but how do I do this? I dont want to have to use linq to extract the entity like this...
var entityFromPage = new MyEntity();
entity.ID = IdFromPage;
entity.Name = UpdatedNameFromPage;
var connectedEntity = _db.MyEntities.Where(x => x.ID == IdFromPage).First();
connectedEntity.ID = entityFromPage.ID;
connectedEntity.Name = entityFromPage.Name;
Because the second part of this script may be massive and I dont want to have to re-map everything. I just want to slot it in on the ID and then call Save() is this possible?
You don't have to.
If you know it already exists on the database,
objectcontext.YourEntities.Attach(entity);
objectcontext.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
objectcontext.SaveChanges();
(If it's a new entity, then you add it to the context)

Categories