2012-05-27 75 views
1

我正在使用實體框架4.3,我試圖創建一個新實體時通過設置導航屬性引用現有實體,但是當我打電話保存EF抱怨說,在我設置導航屬性的表中存在PK違規行爲(即,它正在創建新記錄而不是參考!)。當添加插入新實體並設置對其他實體的引用時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; 
} 

回答

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該插件已經存在於數據庫中,並避免插入這些實體。

編輯

如果你得到錯誤信息......

An entity object cannot be referenced by multiple instances of 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(); 
    } 
} 
+0

嗨Slauma,我與上面運行,完全適用的一個位代碼,在另一個我撤回實體並設置爲成員,然後得到以下錯誤: 「一個實體對象不能被多個IEntityChangeTracker實例引用。 代碼看起來是一樣的,但顯然做了不同的事情是什麼導致這個和任何想法我怎麼能解決它?謝謝。 – g18c

+0

@ g18c:查看我的編輯。如果這不能消除錯誤,則需要提供有關發生錯誤的更多詳細信息。最好問一個新問題,然後因爲問題與你原來的問題無關。 – Slauma

相關問題