微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

asp.net-mvc-3 – 实体框架代码优先:“ObjectStateManager无法跟踪具有相同密钥的多个对象.”

我在MVC3中遇到了Entity Framework代码优先的问题.我正在遇到这个例外:

An object with the same key already exists in the ObjectStateManager.
The ObjectStateManager cannot track multiple objects with the same
key.

在SO上多次解决这个问题,但在我的情况下我无法使用任何建议的解决方案.

这是一个代码示例:

FestORM.SaleMethod method = new FestORM.SaleMethod
{
    Id = 2,Name = "Test Sale Method"
};
FestContext context = new FestContext();

//everything works without this line:
string thisQueryWillMessthingsUp = 
    context.SaleMethods.Where(m => m.Id == 2).Single().Name;

context.Entry(method).State = System.Data.EntityState.Modified;
 context.SaveChanges();

编辑澄清:我正在尝试更新数据库中已存在的对象.

没有代码中注明的查询,一切正常.在我的应用程序中,我的控制器正在实例化上下文,并且相同的上下文被传递给控制器​​使用的几个存储库 – 因此我无法简单地为初始查询操作使用不同的上下文.我试图删除实体在ObjectStateManager中被跟​​踪,但我似乎无法获得任何地方.我试图找出一个适用于这两种情况的解决方案:有时候我会更新一个由ObjectStateManager跟踪的对象,有时它会碰巧还没有被跟踪.

FWIW,我真正的存储库函数看起来像这样,就像上面的代码一样:

public void Update(T entity)
{
    //works ONLY when entity is not tracked by ObjectStateManager
    _context.Entry(entity).State = System.Data.EntityState.Modified; 
}

public void SaveChanges()
{
    _context.SaveChanges();
}

有任何想法吗?我一直在争吵太久了……

解决方法

问题是这个查询

string thisQueryWillMessthingsUp =  
    context.SaleMethods.Where(m => m.Id == 2).Single().Name;

将SaleMethod实体的一个实例带入上下文,然后是此代码

context.Entry(method).State = System.Data.EntityState.Modified;

一个不同的实例附加到上下文中.两个实例都具有相同的主键,因此EF认为您尝试将具有相同键的两个不同实体附加到上下文.它不知道它们都应该是同一个实体.

如果由于某种原因您只需要查询名称,但又不想将完整实体带入上下文,那么您可以这样做:

string thisQueryWillMessthingsUp =           
    context.SaleMethods.Where(m => m.Id == 2).AsNoTracking().Single().Name;

如果您要做的是更新现有实体并且您拥有该实体的所有映射属性的值,那么最简单的方法是不运行查询并只使用:

context.Entry(method).State = System.Data.EntityState.Modified;

如果您不想更新所有属性,可能是因为您没有所有属性的值,那么在调用SaveChanges之前查询实体并在其上设置属性是一种可接受的方法.根据您的具体要求,有几种方法可以做到这一点.一种方法是使用Property方法,如下所示:

var salesMethod = context.SaleMethods.Find(2); // Basically equivalent to your query
context.Entry(salesMethod).Property(e => e.Name).CurrentValue = newName;
context.Entry(salesMethod).Property(e => e.someOtherProp).CurrentValue = newOtherValue;
context.SaveChanges();

这些博客文章包含一些可能有用的其他信息:

http://blogs.msdn.com/b/adonet/archive/2011/01/29/using-dbcontext-in-ef-feature-ctp5-part-4-add-attach-and-entity-states.aspx

http://blogs.msdn.com/b/adonet/archive/2011/01/30/using-dbcontext-in-ef-feature-ctp5-part-5-working-with-property-values.aspx

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐