实体框架更新问题

本文关键字:新问题 更新 框架 实体 | 更新日期: 2023-09-27 18:04:37

我使用实体框架&LINQ检索数据。我在以下方面遇到了问题:

var customer= db.customers.where(c=>c.id==1);
customer.name=santhosh;
customer.city=hyd;

在我调用

之前,数据库中的字段正在变化。
db.SaveChanges();

如何避免这种情况?

实体框架更新问题

正如其他人所说,我相信您在另一个地方也使用了上下文,并且其他位置正在调用savechanges并更新所有内容。试着用@Evan建议的using语句来确保你有一个新的上下文。

AsNoTracking不会确保你得到一个没有缓存在数据库中的实体,它的目的是不把对象放在上下文中。如果您使用AsNoTracking,然后更改查询中返回的实体,您需要在调用savechanges之前将它们作为修改后的实体附加到上下文,否则它们将不会被更新。

    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);

我本想评论一下其他的帖子,但是我还没有足够的知名度。

检查是否将db对象传递给其他方法,并且在那里调用SaveChanges() ?

或者检查你是否有一个异常的捕获块,你可能在捕获块中使用SaveChanges()来记录错误消息?

在我调用

之前,数据库中的字段正在变化。

如果你指的是在应用程序之外的更改,例如SQL Management Studio中的更改。实体框架无法检测到这些变化,因此您可能会得到由实体框架缓存的陈旧对象。要防止接收缓存对象并从数据库获取最新值,请使用AsNoTracking。

试试输入AsNoTracking():

var customer= db.customers.AsNoTracking().where(c=>c.id==1);
customer.name=santhosh;
customer.city=hyd;
db.SaveChanges();

或者如果你的问题是检测对同一行的并发更新(不幸的术语,它不适用于UPDATE),使用rowversion(又名时间戳)字段类型;然后在你的。net代码中添加Timestamp属性。例如: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; }
    [Timestamp]
    public virtual byte[] Version { get; set; }
}

UPDATE (after your comment):

如果你真的不打算持久化你的对象到数据库。尝试分离对象。

试试这个:

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();

这将不会保存您的更改名称和城市到数据库。

如果你想要一些更健壮的东西(如果对象还没有被附加,上面的代码会因为异常而失败),创建一个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;
}

使用:Evict(yourDbContextHere, typeof(Product), "ProductId", 1);

http://www.ienablemuch.com/2011/08/entity-frameworks-nhibernate.html

您能提供更多的周围代码吗?如果不知道如何构建上下文,可能会有点困难。

这是我通常处理更新的方式(我希望它能给一些启示):

       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,你的方法对我没用。

我不得不为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();