Jos*_*osh 5 entity-framework repository code-first asp.net-mvc-3 dbcontext
我在MVC3中遇到了Entity Framework代码优先的问题.我正在遇到这个例外:
ObjectStateManager中已存在具有相同键的对象.ObjectStateManager无法使用相同的键跟踪多个对象.
在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();
Run Code Online (Sandbox Code Playgroud)
编辑澄清:我正在尝试更新数据库中已存在的对象.
没有代码中注明的查询,一切正常.在我的应用程序中,我的控制器正在实例化上下文,并且相同的上下文被传递给控制器使用的几个存储库 - 因此我无法简单地为初始查询操作使用不同的上下文.我试图删除实体在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();
}
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?我一直在争吵太久了......
Art*_*ers 12
问题是这个查询
string thisQueryWillMessThingsUp =
context.SaleMethods.Where(m => m.Id == 2).Single().Name;
Run Code Online (Sandbox Code Playgroud)
将SaleMethod实体的一个实例带入上下文,然后是此代码
context.Entry(method).State = System.Data.EntityState.Modified;
Run Code Online (Sandbox Code Playgroud)
将一个不同的实例附加到上下文中.两个实例都具有相同的主键,因此EF认为您尝试将具有相同键的两个不同实体附加到上下文.它不知道它们都应该是同一个实体.
如果由于某种原因您只需要查询名称,但又不想将完整实体带入上下文,那么您可以这样做:
string thisQueryWillMessThingsUp =
context.SaleMethods.Where(m => m.Id == 2).AsNoTracking().Single().Name;
Run Code Online (Sandbox Code Playgroud)
如果您要做的是更新现有实体并且您拥有该实体的所有映射属性的值,那么最简单的方法是不运行查询并只使用:
context.Entry(method).State = System.Data.EntityState.Modified;
Run Code Online (Sandbox Code Playgroud)
如果您不想更新所有属性,可能是因为您没有所有属性的值,那么在调用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();
Run Code Online (Sandbox Code Playgroud)
这些博客文章包含一些可能有用的其他信息:
| 归档时间: |
|
| 查看次数: |
6588 次 |
| 最近记录: |