Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/asp.net-mvc-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 3 首先是实体框架代码:“quot;ObjectStateManager无法跟踪具有相同密钥的多个对象。”;_Asp.net Mvc 3_Entity Framework_Repository_Code First_Dbcontext - Fatal编程技术网

Asp.net mvc 3 首先是实体框架代码:“quot;ObjectStateManager无法跟踪具有相同密钥的多个对象。”;

Asp.net mvc 3 首先是实体框架代码:“quot;ObjectStateManager无法跟踪具有相同密钥的多个对象。”;,asp.net-mvc-3,entity-framework,repository,code-first,dbcontext,Asp.net Mvc 3,Entity Framework,Repository,Code First,Dbcontext,在MVC3中,我首先遇到了实体框架代码的问题。我遇到了一个例外: ObjectStateManager中已存在具有相同密钥的对象。 ObjectStateManager无法跟踪具有相同属性的多个对象 钥匙 这个问题已经解决了很多次了,但在我的情况下,我很难使用任何建议的解决方案 下面是一个代码示例: FestORM.SaleMethod method = new FestORM.SaleMethod { Id = 2, Name = "Test Sale Method" }; F

在MVC3中,我首先遇到了实体框架代码的问题。我遇到了一个例外:

ObjectStateManager中已存在具有相同密钥的对象。 ObjectStateManager无法跟踪具有相同属性的多个对象 钥匙

这个问题已经解决了很多次了,但在我的情况下,我很难使用任何建议的解决方案

下面是一个代码示例:

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

有什么想法吗?我对此已经争论太久了…

显而易见的答案是,在调用之前,您实际上没有将方法对象保存到数据库中:

//everything works without this line:
string thisQueryWillMessThingsUp = context.SaleMethods.Where(m => m.Id == 2).Single().Name;
然而,我想这可能只是你遗漏了一点代码。 如果你让你的实体从一个抽象类继承呢

public abstract class BaseClass
{
     public int Id { get; set; }
}
然后将存储库更新为

public class Repository<T> where T : BaseClass
{
 .....
    public void Update(T entity)
    {        
        _context.Entry(entity).State = entity.Id == 0 ? System.Data.EntityState.Added : System.Data.EntityState.Modified; 
    }
}
公共类存储库,其中T:BaseClass
{
.....
公共无效更新(T实体)
{        
_context.Entry(entity).State=entity.Id==0?System.Data.EntityState.Added:System.Data.EntityState.Modified;
}
}
另外,您可能不希望设置SaleMethod的ID,而让它由数据库生成。问题还可能是因为数据库中SaleMethod对象的Id为2,然后您尝试添加另一个Id为2的SaleMethod对象。
您看到的错误源于尝试将另一个ID为2的SaleMethod对象添加到ObjectStateManager。

问题在于此查询

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();
这些博客文章包含一些可能有用的附加信息:


谢谢您的回复。是的,ID肯定是由数据库生成的。这是一个具体的更新操作。我确实遗漏了对象最初保存的部分(可能在几年前由另一段代码最初保存,等等)。问题是,只要不先执行查询,更新就可以正常工作。执行查询显然会将其添加到ObjectStateManager的跟踪中,此时我的更新会发出嘎嘎声。谢谢。(这不会让我投票支持你的回答,因为我是新来的。)问题是,我不知道在将来的更新之前我什么时候做查询。查询可能隐藏在服务层的某个地方,然后最终,当我在查询的同一个实体上执行更新时,我遇到了错误。有没有一种方法可以将对象从上下文跟踪中移除,或者获取上下文跟踪的对象,并向上下文传达我确实正在更新这一个有问题的对象?我已经在这个方向上做了一些研究,但还没有成功。这取决于查询的意图。如果查询的目的是将一个实体带入上下文,以便可以更新和保存(这是很常见的),那么您应该为此进行设计,可能是在保存之前确保该实体被带入,如果它以前没有被带入的话。如果查询的目的是出于某种原因从数据库中获取实体的某些属性,而不将该实体带入上下文,则在该查询上使用AsNoTracking,如上所示。要添加到我之前的注释中,如果要确保已引入该实体,然后在更新实体中的属性并保存之前使用Find方法。您还可以使用查询而不是Find——默认情况下,只有实体不在上下文中时,查询才会引入实体。但是Find更有效。目前我有一组属性由viewmodel返回。viewmodel还包含正在更新的项的ID。我正在用这些数据实例化一个新对象。viewmodel不包含基础模型的所有属性,因此我通过查询获取这些缺少的属性,以填充到我的新(更新)对象中。然后我尝试保存(更新)对象。相反,我只需要先执行一个查询来获取我的对象,然后使用返回的viewmodel中的信息更新该对象的属性(而不是执行相反的操作)。听起来对吗?