I am using Entity Framework 4.3 and I am trying to reference an existing entity by setting the navigation property when creating a new entity, however when i call save EF complains that there is a PK violation in the table for which i set the navigation property to (i.e. it is creating a new record as opposed to a reference!).
How can i attach to an existing POCO as opposed to referencing it and having EF trying to create a new database record (but not simply use an ID, ideally i would like to reference an actual entity that came from another query)?
Thanks in advance,
Chris
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;
}
You must attach the existing entities to the context:
…where
unitOfWork.ExternalPluginRepository.Attach(ExternalPlugin plugin)must do:I expect that all repositories use the same context instance.
Attachtells EF that the plugins already exist in the database and avoids an INSERT of those entities.Edit
If you get the error message…
…it means that you have an entity that is attached to more than one context instance at the same time. You can avoid that in most cases by disposing the context always when you don’t need it anymore. Your code sample does not follow this good practice. It rather should look like this:
At the end of the
usingblock theDisposemethod of theunitOfWorkis called automatically. To get this working (and compiling as well) you need to derive yourIUnitOfWorkinterface fromIDisposableand implement it in the concreteUnitOfWorkclass: