1

我正在使用实体框架 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;
}
4

1 回答 1

2

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

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块的末尾,会自动调用的Dispose方法。unitOfWork要使其正常工作(以及编译),您需要IUnitOfWork从具体类派生接口IDisposable并在具体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();
    }
}
于 2012-05-27T17:47:11.973 回答