6

我正在開發一個帶EF6的插件應用程序,代碼優先。實體框架:跨不同的DbContexts共享實體

我有一個實體的一個主要方面稱爲User

public class MainDataContext : DbContext 
{ 
    public MainDataContext(): base("MainDataContextCS") {} 
    public DbSet<User> Users { get; set; } 
} 

然後另一個上下文PluginX,在另一個項目,引用基地之一:

public class PluginDataContext : DbContext 
{ 
    public PluginDataContext() : base("MainDataContextCS") { 
    } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) { 
     modelBuilder.HasDefaultSchema("PluginX"); 
     base.OnModelCreating(modelBuilder); 
    } 

    public DbSet<Booking> Bookings { get; set; } 
} 

這整齊地創建,在同一個數據庫(相同的連接字符串)上,PluginX.Bookings表。

的這裏的問題是,Booking實體包含User實體的引用:

public class Booking 
{ 
    public int Id { get; set;} 
    public virtual User CreationUser { get; set;} 
    public BookingStatus Status { get; set; } 
} 

而對於插件上下文運行Add-Migration當EF將嘗試創建另一個User實體,稱爲PluginX.User

這怎麼解決?有沒有辦法共享一個共同的實體,在另一個DbContext

+0

爲什麼不從MainContext繼承PluginContext。 – hazimdikenli 2015-01-16 07:32:36

回答

5

當你與多個環境工作,你有兩個選擇:

  1. 對待每一個方面像他們單獨的應用程序。想象一下,您的用戶是從Web服務獲得的外部資源。您將無法爲其添加外鍵。你要做的是在你的表中只添加userId,當你需要用戶的詳細信息時調用外部服務來獲取它們,或者在Bookings上下文中有一個用戶的本地光照副本,你可以隨時更新來自用戶上下文。當您使用大型系統並且要分離部件時(閱讀關於DDD和有界的上下文),這種方法非常好。
  2. 從您的2個上下文中創建第三個上下文(用戶,預訂等) )。您將使用完整的上下文來創建遷移並維護數據庫結構,但在應用程序中,您將使用較小的上下文。這是一個非常簡單的解決方案。使用單個上下文維護遷移很容易,它仍然允許您在較小的上下文中隔離數據庫操作,而這些上下文無法訪問不相關的實體。
1

添加預訂實體時,請勿使用DbSet.Add()方法。請使用DbSet.Attach()方法並將預訂的DbContext.Entry(Entity).State屬性設置爲EntityState.Added,並確保用戶的DbContext.Entry(Entity).StateEntityState.Unchanged

因此,例如,而不是這樣做:

pluginDataContext.dbBooking.Add(myNewBooking); 

這樣做:

pluginDataContext.dbBooking.Attach(myNewBooking); 
pluginDataContext.Entry(myNewBooking).State = EntityState.Added; 

這是因爲Add()方法標誌着對象圖中的所有實體EntityState.Added這將導致插入,而不檢查如果實體已經存在於數據庫中。方法只是簡單地使上下文開始跟蹤實體。

這就是爲什麼我幾乎從不使用DbSet.Add()

2

此解決方案可以幫助您:Entity Framework 6 Code First Migrations with Multiple Data Contexts。但是,在這種情況下,兩個上下文都在同一個項目中。我不知道是否可以在兩個不同的項目中使用上下文(我認爲應該使用相同的類來映射用戶)。正如博客所說,當您爲PluginX上下文運行Add-Migration命令時,您需要評論與Users表相關的生成代碼。