I am using Entity Framework & LINQ to retrieve data. I am having a problem with the following:
var customer= db.customers.where(c=>c.id==1);
customer.name=santhosh;
customer.city=hyd;
The fields are changing in the database before I call:
开发者_运维问答db.SaveChanges();
How do I avoid this?
As others have said, I believe that you are using your context in another place as well and that other location is calling savechanges and updating everything. Try doing what @Evan suggested with a using statment to make sure you have a fresh context.
AsNoTracking will not ensure that you get a entity that is not cached in the database, its purpose is to not put the objects inside the context. If you use AsNoTracking and then change the entities returned in the query you will need to attach them as modified to the context before calling savechanges or else they won't be updated.
var customer= db.customers.AsNoTracking().Single(c=>c.id==1);
customer.name=santhosh;
customer.city=hyd;
ctx.customers.Attach(customer);
ctx.ObjectStateManager.ChangeObjectState(customer, System.Data.EntityState.Modified);
I would have just commented on the other posts but don't have enough rep yet.
Check whether you are passing the db object to some other method, and SaveChanges() is called there?
Or check whether you have a catch block of an exception and you might be using SaveChanges() in the catch block to log error message?
(These are common programming mistakes)
The fields are changing in the database before I call
If you mean changing as in changing outside of application, changes in SQL Management Studio for example. Entity Framework cannot detect those changes, so as a result you might get stale objects that was cached by Entity Framework. To prevent receiving cached object and get the up-to-date values from database, use AsNoTracking.
Try putting AsNoTracking():
var customer= db.customers.AsNoTracking().where(c=>c.id==1);
customer.name=santhosh;
customer.city=hyd;
db.SaveChanges();
Or if your problem is to detect concurrent updates(unfortunate terminology, it doesn't apply to UPDATE only) to same row, use rowversion(aka timestamp) field type; then on your .NET code add Timestamp
attribute on the property. Example: http://www.ienablemuch.com/2011/07/entity-framework-concurrency-checking.html
public class Song
{
[Key]
public int SongId { get; set; }
public string SongName { get; set; }
public string AlbumName { get; set; }
1679777208
public virtual byte[] Version { get; set; }
}
UPDATE (after your comment):
If you really has no intent to persist your object changes to database. Try detaching the object.
Try this:
var customer= db.customers.where(c=>c.id==1);
db.Entry(customer).State = System.Data.EntityState.Detached; // add this
customer.name=santhosh;
customer.city=hyd;
db.SaveChanges();
That won't save your changes on name and city to database.
If you want something more robust(the above will fail an exception if the object was not yet attached), create a helper:
private static void Evict(DbContext ctx, Type t,
string primaryKeyName, object id)
{
var cachedEnt =
ctx.ChangeTracker.Entries().Where(x =>
ObjectContext.GetObjectType(x.Entity.GetType()) == t)
.SingleOrDefault(x =>
{
Type entType = x.Entity.GetType();
object value = entType.InvokeMember(primaryKeyName,
System.Reflection.BindingFlags.GetProperty,
null, x.Entity, new object[] { });
return value.Equals(id);
});
if (cachedEnt != null)
ctx.Entry(cachedEnt.Entity).State = EntityState.Detached;
}
To use: Evict(yourDbContextHere, typeof(Product), "ProductId", 1);
http://www.ienablemuch.com/2011/08/entity-frameworks-nhibernate.html
Can you give a little more of the surrounding code? Might be a little difficult without seeing how you are constructing your context.
This is how I typically handle updates (I hope it might give some insight):
using (var ctx = new myModel.myEntities())
{
int pollID = 1;
var poll = (from p in ctx.Polls
where p.PollID == pollID
select p).FirstOrDefault();
poll.Question = txtPoll.Text.Trim();
ctx.SaveChanges();
}
Jack Woodward, yours did not work for me.
I had to change it up a little for SQL Compact.
var customer= db.customers.AsNoTracking().Single(c=>c.id==1);
db.customers.Attach(customer);
customer.name=santhosh;
customer.city=hyd;
db.ObjectStateManager.ChangeObjectState(customer, System.Data.EntityState.Modified);
db.SaveChanges();
db.Dispose();
This worked alot better.
精彩评论