加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-mvc-3 – 实体框架代码优先:“ObjectStateManager无法

发布时间:2020-12-16 03:39:09 所属栏目:asp.Net 来源:网络整理
导读:我在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上多次解决这个问题,但在我
我在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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读