添加插入新实体并设置对其他实体的引用时(其他实体)的 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;
}
必须将现有实体附加到上下文:
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
块结束时,将自动调用unitOfWork
的Dispose
方法。要使其正常工作(以及编译),您需要从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();
}
}