Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.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
C# 唯一索引冲突,试图在新上下文上插入对象图_C#_.net_Asp.net_Entity Framework_Entity Framework 4 - Fatal编程技术网

C# 唯一索引冲突,试图在新上下文上插入对象图

C# 唯一索引冲突,试图在新上下文上插入对象图,c#,.net,asp.net,entity-framework,entity-framework-4,C#,.net,Asp.net,Entity Framework,Entity Framework 4,参考下面的代码,我有一个Error对象列表,这些对象已被实例化以供插入。已为每个错误分配了一个从数据库检索的ErrorType对象。当我尝试在新上下文中插入错误列表时,我从ErrorType上的唯一索引冲突数据库中得到一个异常。这是有意义的,因为新上下文假定ErrorType对象也是新的,而不知道它已经存在于数据库中。我试图通过在ErrorType上使用Attach来解决这个问题,并重新查询数据库中的所有ErrorType,但是这似乎没有帮助。我运行了SQL探查器,仍然看到EF在ErrorTyp

参考下面的代码,我有一个
Error
对象列表,这些对象已被实例化以供插入。已为每个错误分配了一个从数据库检索的
ErrorType
对象。当我尝试在新上下文中插入错误列表时,我从ErrorType上的
唯一索引冲突
数据库中得到一个异常。这是有意义的,因为新上下文假定ErrorType对象也是新的,而不知道它已经存在于数据库中。我试图通过在ErrorType上使用Attach来解决这个问题,并重新查询数据库中的所有ErrorType,但是这似乎没有帮助。我运行了SQL探查器,仍然看到EF在ErrorType实体上发出insert语句

编辑:我还添加了“Try 1.5”,它与“Try 1”一起实际起作用。我仍然不明白为什么我必须返回并更改所有error.ErrorType引用以指向本地创建和附加的ErrorType对象。我知道原始ErrorType和本地创建的ErrorType在内存中是不同的对象,但它们共享相同的PrimaryKey,所以我的假设是实体框架理解它们是一个相同的对象

似乎我也无法附加原始FileErrorType(与本地相反),因为它随后会尝试附加整个图形,这就是为什么我选择创建具有相同主键值的FileErrorType对象的本地副本

void InsertErrors(IList<Error> errors)
{
    using(var context = ....)
    {
        //Try 1:
        //asuming there is only 1 error type (true in my example)
        //ErrorType et = new ErrorType();
        //ErrorTypeId is the primary key
        //et.ErrorTypeId = errors[0].ErrorType.ErrorTypeId;
        //context.ErrorTypes.Attach(et);

        //Try 1.5
        //If I also add the followin code to Try 1, everything works, but I'm not sure why
        //foreach(var e in errors)
        //{
        //    error.ErrorType = et; //reassign to the locally created ErrorType object that has been Attached
        //}

        //Try 2:
        //var errorTypes = context.ErrorTypes.ToList();

        foreach(var e in errors)
        {
            context.Errors.AddObject(e);        
        }       

        context.SaveChanges();
    }
}
void插入错误(IList错误)
{
使用(变量上下文=…)
{
//尝试1:
//asuming只有1种错误类型(在我的示例中为true)
//ErrorType et=新的ErrorType();
//ErrorTypeId是主键
//et.ErrorTypeId=错误[0]。ErrorType.ErrorTypeId;
//context.ErrorTypes.Attach(et);
//试试1.5
//如果我还添加了以下代码来尝试1,那么一切都正常,但我不知道为什么
//foreach(错误中的变量e)
//{
//error.ErrorType=et;//重新分配给本地创建的已附加的ErrorType对象
//}
//尝试2:
//var errorTypes=context.errorTypes.ToList();
foreach(错误中的变量e)
{
context.Errors.AddObject(e);
}       
SaveChanges();
}
}

添加错误时,它们和相关的错误类型将标记为已添加,并在调用SaveChanges时插入数据库


一旦所有ErrorType实例与上下文关联,就调用attach。这会将ErrorType的状态更改为未修改,并防止在SaveChanges期间插入它们。

事实上,这正是我所做的。如果您阅读我的“Try 1”中的注释,您将看到我只有1个ErrorType实例。换句话说,如果您证明所有error.ErrorType,它们都指向具有相同id的相同实体。因此对列表中的第一个实体调用Attach就足够了。在方法1中,您正在创建一个新的本地ErrorType实例。我假设errors参数中的Error对象已经引用了ErrorType实例(即使它们都指向同一个实例)。您不需要创建新的本地实例,而只需在带有错误参数的现有实例上调用Attach。我最初尝试这样做,但是Attach尝试以未修改的形式附加整个图形,这意味着所有错误以及所有错误类型。这会导致引发异常,因为Attach不允许对图形中的同一对象进行多个引用。我读到的另一种方法是调用AddObject(),然后手动将所有ErrorType对象的状态设置为unchanged。我想我的总体问题是,为什么EF上下文不能将ErrorType的本地副本识别为与已附加到错误的副本相同的东西。Id是相同的。关键是首先添加错误,然后附加错误类型。它们将与错误一起拖到上下文中,因此只需附加errortypes即可将状态设置为未修改。您不需要手动创建本地errortype,因此作为副本也不会有任何问题。是的,您描述的是我在之前的评论中建议的替代方法。老实说,我没有走这条路,因为我有一个实现Attach的通用存储库,但不公开其他方法来更改实体的状态。我在上面发布的代码只是一个示例,可以简化我的场景并让大家明白这一点。我想我的核心问题是EF如何跟踪实体。它似乎不仅仅是实体类型及其主键,它实际上也是内存引用?