1

我在兩個服務項目之間共享的程序集中有一個DbContext。我將這兩個項目設置爲在Visual Studio中開始進行調試。這會在每個服務中的DatabaseInitializer嘗試在啓動時更新數據庫時創建爭用條件。顯式調用DatabaseInitializer

爲了防止發生這種情況,我修改了我的DbContext,如下所示,以免DatabaseIntializer被自動註冊。

public EntityContext : DbContext 
{ 
    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     Database.SetInitializer<EntityContext>(null); 
    } 
} 

我想禁用DatabaseInitializerDbContext本身裏面,這樣我就不必複製該SetInitializer()通話中每個項目所發生引用我DbContext,以及基於什麼我讀,覆蓋OnModelCreating()似乎要做到這一點。

這可以防止DatabaseInitializer自動運行,但我想創建一個單獨的項目,我可以手動運行以更新數據庫。所以,我不喜歡的東西如下:

static void Main(string[] args) 
{ 
    Database.SetInitializer(new CreateDatabaseIfNotExists<EntityContext>()); 
    new EntityContext().Database.Initialize(true); 
} 

的問題是,這似乎並沒有工作 - 空初始化在OnModelCreating()方法設置顯然會覆蓋任何東西,我在任何其他呼叫指定SetInitializer()。即使我將SetIntializer(null)調用移動到EntityContext類的靜態構造函數,以確保它首先被調用,但它仍然不起作用。它的工作的唯一方法是,如果我手動調用初始化如下:

static void Main(string[] args) 
{ 
    new CreateDatabaseIfNotExists<EntityContext>() 
     .InitializeDatabase(new EntityContext()); 
} 

但在調用DatabaseInitializer.InitializeDatabase()直接看起來不正確,因爲實體框架的基礎設施應該調用。

這是EF Code First中的一個錯誤嗎?什麼是「正確」的方式去做這件事?

更新:我決定用Update-Database軟件包管理器控制檯命令手動創建數據庫腳本比嘗試以編程方式更新數據庫的kludgey項目更好。

回答

1

只要在禁用初始化程序的調用之後設置初始化程序的調用就會生效。 OnModelCreating或靜態EntityContext初始值設定程序都不會這樣做。靜態初始化程序只會在第一次使用EntityContext時調用,在您的示例中,只有在調用SetInitializer之後纔會調用該初始化程序。

在進行SetInitializer調用之前,您可以考慮強制調用靜態初始化程序。例如,這應該工作:

using (var context = new EntityContext()) 
{ 
    Database.SetInitializer(new CreateDatabaseIfNotExists<EntityContext>()); 
    context.Database.Initialize(true); 
} 
+0

很好的捕獲...但即使該代碼只適用於如果我去靜態構造函數路由。原因在於它實際上是調用'Initialize()'來觸發對'OnModelCreated()'的調用。我現在傾向於認爲直接調用初始化器會更好地表達我的意圖。 – luksan

+1

這是因爲DbContext故意非常懶惰,並且做了很少的工作,包括初始化,直到您以某種方式實際使用它。這意味着您不必知道(從perf的角度來看)在創建實例之前您將使用DbContext,這可能非常有用。 –