【问题标题】:unique index violation, attempting to insert object graph on new context唯一索引违规,试图在新上下文中插入对象图
【发布时间】:2011-08-02 12:27:16
【问题描述】:

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

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

似乎我无法附加原始 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();
    }
}

【问题讨论】:

    标签: c# .net asp.net entity-framework entity-framework-4


    【解决方案1】:

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

    在所有 ErrorType 实例与上下文关联后调用 attach。这会将 ErrorTypes 的状态更改为 Unmodified 并防止它们在 SaveChanges 期间插入。

    【讨论】:

    • 其实我就是这么做的。如果您阅读我的“Try 1”中的评论,您会发现我只有 1 个 ErrorType 实例。换句话说,如果你证明所有error.ErrorType,它们都指向具有相同id的同一个实体。因此,对列表中的第一个调用 Attach 就足够了。除非我没有理解你的意思。
    • 在方法 1 中,您正在创建一个新的本地 ErrorType 实例。我假设 errors 参数中的 Error 对象已经引用了 ErrorType 实例(即使它们都指向同一个)。您不需要创建新的本地实例,只需在带有错误参数的现有实例上调用 Attach。
    • 我最初尝试这样做,但是 Attach 尝试以未修改的形式附加整个图表,这意味着所有错误以及所有错误类型。这会导致抛出异常,因为 Attach 不允许对图中的同一对象进行多个引用。我读到的替代方法是调用 AddObject() 然后手动将所有 ErrorType 对象的状态设置为未更改。我想我的总体问题是,为什么 EF 上下文不将 ErrorType 的本地副本识别为与已经附加到错误的副本相同。 Id 是一样的。
    • 关键是先添加错误,然后附加错误类型。它们已经与错误一起被拖到上下文中,因此仅需要附加错误类型才能将状态设置为未修改。您不需要手动创建本地错误类型,因此也不应该有任何重复的问题。
    • 是的,您所描述的是另一种方法,正如我在之前的评论中所建议的那样。老实说,我没有走这条路,因为我有一个实现 Attach 的通用存储库,但没有公开其他方法来更改实体的状态。我在上面发布的代码只是一个示例,用于简化我的场景并理解重点。我想我的核心问题是 EF 如何跟踪实体。似乎不仅仅是实体类型及其主键,它也是实际的内存引用?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 2012-09-10
    • 2018-06-28
    相关资源
    最近更新 更多