首先在实体框架模型中关闭跟踪

Posted

技术标签:

【中文标题】首先在实体框架模型中关闭跟踪【英文标题】:Turn off tracking in entity framework model first 【发布时间】:2011-10-23 12:51:52 【问题描述】:

我想接收一个实体然后更新它,但我想在不跟踪的情况下获取它,所以我可以将它附加回上下文。

我引用了EntityFramework.dll (4.1)。我从模型生成了数据库。 (不是代码优先)。

获取用户:

db.Users.MergeOption = MergeOption.NoTracking;
IQueryable<User> query = db.Users;//.AsNoTracking(); //<-- apparently, this is code-first only.

return query;

更新用户:

db.Users.Attach(user); //error here.
ObjectStateEntry entry = db.ObjectStateManager.GetObjectStateEntry(user);
entry.SetModifiedProperty(propertyName);
db.SaveChanges();
return user;

错误:

ObjectStateManager 中已存在具有相同键的对象。 ObjectStateManager 无法跟踪具有相同键的多个对象。

我这样调用方法:

var user = userRepository.GetUsers().FirstOrDefault(u => u.UserId == userId);
user.Identifiers.Add(someIdent);
userRepository.UpdateUser(user);

【问题讨论】:

它应该可以工作。您确定您没有收到用户的其他查询吗? @Ladislav 相同的查询。我在存储库中只有 1 个读取/获取方法,它使用该代码 我刚刚测试了类似的代码,没有任何存储库负担,它对我有用。 这看起来不是问题,但我不明白你为什么要使用NoTracking,如果你要再次将它附加回相同的上下文并保存它。 NoTracking 适用于您不想更改实体的场景。 user.Identifiers.Add(someIdent); 中的标识符是什么,这也是一个实体吗?如果是这样,那可能是导致“相同的密钥已经存在”错误的原因吗? 【参考方案1】:

而不是分离和附加。如果您想处理更新可能来自或不来自原始上下文的项目,您可以执行以下操作。

var originalItem = db.Users.Find(user.UserId);
db.Entry(originalItem).CurrentValues.SetValues(user);
db.SaveChanges();

【讨论】:

当我的对象(originalItem)具有一个子实体集合的属性时,这似乎对我不起作用。对于这种情况,我需要做些什么特别的事情吗?【参考方案2】:

无跟踪查询 有时您可能想要查询实体但不让实体被上下文跟踪。在只读场景中查询大量实体时,这可能会带来更好的性能。 AsNoTracking 扩展方法执行查询并返回结果,而不在上下文中跟踪它们。在以下示例中,查询将返回对象,但不会被上下文跟踪。 其他

       // Query for all departments without tracking them
       var departments1 = context.Departments.AsNoTracking().ToList();

      // Query for some departments without tracking them
      var departments2 = context.Departments
                .Where(d => d.Name.StartsWith("math"))
                .AsNoTracking()
                .ToList();

【讨论】:

以上是关于首先在实体框架模型中关闭跟踪的主要内容,如果未能解决你的问题,请参考以下文章

如何从作为wpf mvvm模式中的窗口打开的视图模型中关闭用户控件?

管道实现生产者消费者模型

如何在 .Net Core 3.1 Web 应用程序中关闭 Application Insights 性能计数器和跟踪遥测

Android中关闭应用的三种方式

在 Macbook PRO 中关闭 NSWindow 时 CEF 崩溃(仅在触摸板上不用于鼠标单击)

在 Xcode 7 UI 自动化中关闭 Touch Id 操作