添加插入新实体并设置对其他实体的引用时(其他实体)的 PK 冲突

本文关键字:实体 其他 引用 冲突 PK 新实体 插入 添加 设置 | 更新日期: 2023-09-27 18:35:25

我正在使用实体框架 4.3,并且我正在尝试通过在创建新实体时设置导航属性来引用现有实体,但是当我调用 save EF 时,抱怨我在将导航属性设置为的表中存在 PK 冲突(即它正在创建新记录而不是引用!

如何附加到现有 POCO,而不是引用它并让 EF 尝试创建新的数据库记录(但不是简单地使用 ID,理想情况下我想引用来自另一个查询的实际实体)?

提前感谢,

克里斯

public class BusinessUnit
{
    public int BusinessUnitID { get; set; }
    public ExternalPlugin AccountsDataSourceModule { get; set; }
    public ExternalPlugin OptionalContactsDataSourceModule { get; set; }
}
public BusinessUnit NewBusinessUnit(string name, ExternalPlugin accountsModuleId = null, ExternalPlugin contactsModuleId = null)
{
    IUnitOfWork unitOfWork = UnitOfWorkFactory.CreateUnitOfWork();
    BusinessUnit unit = new BusinessUnit();
    unit.CompanyName = name;
    unit .AccountsDataSourceModule = accountsModuleId; // this causes a problem
    unit .OptionalContactsDataSourceModule = contactsModuleId; // as does this
    unitOfWork.BusinessUnitRepository.Insert(unit);
    unitOfWork.Save();
    return unit;
}

添加插入新实体并设置对其他实体的引用时(其他实体)的 PK 冲突

必须将现有实体附加到上下文:

BusinessUnit unit = new BusinessUnit();
unit.CompanyName = name;
unitOfWork.ExternalPluginRepository.Attach(accountsModuleId);
unitOfWork.ExternalPluginRepository.Attach(contactsModuleId);
unit.AccountsDataSourceModule = accountsModuleId;
unit.OptionalContactsDataSourceModule = contactsModuleId;
unitOfWork.BusinessUnitRepository.Insert(unit);

unitOfWork.ExternalPluginRepository.Attach(ExternalPlugin plugin)必须做的事情:

context.ExternalPlugins.Attach(plugin);

我希望所有存储库都使用相同的上下文实例。 Attach告诉 EF 插件已存在于数据库中,并避免插入这些实体。

编辑

如果您收到错误消息...

实体对象不能由多个实例引用 IEntityChangeTracker.

。这意味着您有一个同时附加到多个上下文实例的实体。在大多数情况下,您可以通过在不再需要上下文时始终释放上下文来避免这种情况。您的代码示例不遵循此良好做法。它应该看起来像这样:

public BusinessUnit NewBusinessUnit(string name,
    ExternalPlugin accountsModuleId = null,
    ExternalPlugin contactsModuleId = null)
{
    using (IUnitOfWork unitOfWork = UnitOfWorkFactory.CreateUnitOfWork())
    {
        BusinessUnit unit = new BusinessUnit();
        unit.CompanyName = name;
        unitOfWork.ExternalPluginRepository.Attach(accountsModuleId);
        unitOfWork.ExternalPluginRepository.Attach(contactsModuleId);
        unit.AccountsDataSourceModule = accountsModuleId;
        unit.OptionalContactsDataSourceModule = contactsModuleId;
        unitOfWork.BusinessUnitRepository.Insert(unit);
        unitOfWork.Save();
        return unit;
    }
}

using块结束时,将自动调用unitOfWorkDispose方法。要使其正常工作(以及编译),您需要从IDisposable派生IUnitOfWork接口,并在具体的UnitOfWork类中实现它:

public interface IUnitOfWork : IDisposable
{
    // ...
}
public class ConcreteUnitOfWork : IUnitOfWork, IDisposable
{
    private MyDbContext _context;
    // I assume that you have a member for the DbContext in this class
    // ...
    // implementation of IDisposable
    public void Dispose()
    {
        if (_context != null)
            _context.Dispose();
    }
}