2015-06-22 96 views
2

我正在使用實體框架(最新版本 - 我們所說的6.0)和最新的.NET版本(我們所說的版本4.5.1)編寫應用程序。使用實體框架代碼首先使用動態連接字符串

我面臨的問題是我想使用代碼優先的方法,因爲我非常喜歡它,但應用程序由各種數據庫組成。現在,添加遷移和更新數據庫不是問題。即使實體框架需要跟蹤多個上下文對象,我也知道這個命令。

但是,這裏是其中我負責的具體情況:

  • 我使用包含各種用戶的通用的「設置」數據庫,每個用戶都有它特定的設置。每個用戶通用的一個設置是數據庫連接字符串。

這確實意味着我有一個設置表,其中可以配置5個用戶,但每個用戶確實需要另一個數據庫(但數據庫的結構在每個數據庫中都是相同的)。我們爲什麼使用不同的數據庫有非常具體的原因,即使模型是相同的,但我不會詳細介紹這些。

現在,問題是我需要如何在我的Visual Studio項目中定義我的第二個上下文。我知道在我的DbContext的構造函數中,我可以傳遞連接字符串,所以在運行時完全沒有問題,但是在開發時,我還使用NuGet程序包管理器來管理數據庫的遷移。

有沒有什麼辦法可以一次升級所有的數據庫(或一次一個),但是通過獲取存儲在數據庫中的連接字符串(因爲它取決於用戶)?

親切的問候

+0

我會想到將數據庫遷移到單獨的進程,但不是在正常執行應用程序期間。這個過程可能需要獨佔訪問數據庫。 –

+0

我正在處理某件事情,但這並不完全。也許你對如何用連接字符串而不是連接字符串名稱來調用'Database.SetInitializer'有任何想法。 – Complexity

+0

我想你可以用'DbConnection'參數構建'DbContext',你可以像你一樣創建f.e.您可以將連接字符串傳遞給'SqlConnection'構造函數。 –

回答

2

好吧,我設法找到一個解決辦法我自己,我與它很高興。

首先,我將展示應用程序的結構。

我有一個DbContext稱爲AppServerSettingsContext這是在源代碼中定義是這樣的:

/// <summary> 
///  Initializes a new instance of the <see cref="AppServerSettingsDataContext"/>. 
/// </summary> 
public AppServerSettingsDataContext() 
    : base("AppServerSettingsDataContext") 
{ } 

該上下文有2層不同的實體(一個用於一個構件,一個用於該特定部件的所有設置) 。

爲了能夠執行遷移,我需要在應用程序配置文件中有一個ConnectionString,就像我們使用的方式一樣。

然後,我有另一個名爲AppServerDataContext的上下文。 這有2個構造如下表現:

/// <summary> 
///  Initializes a new instance of the <see cref="AppServerDataContext"/>. 
/// </summary> 
public AppServerDataContext() : 
    this(ConfigurationManager.ConnectionStrings["AppServer"].ConnectionString) 
{ } 

/// <summary> 
///  Initializes a new instance of the <see cref="AppServerDataContext"/>. 
/// </summary> 
/// <param name="connectionString">The full connection string which is used to connect to the database.</param> 
public AppServerDataContext(string connectionString) 
    : base(connectionString) { } 

你會在這我可以指定連接字符串或我加載應用程序配置文件中的連接字符串代碼中看到。

你會明白爲什麼這很重要。

我有DbContext指向配置文件中的連接字符串。這並不是必須的,但我習慣這樣工作。因此只有在調用add-migration命令時纔會使用連接字符串。這是因爲該命令需要數據庫檢查數據庫的當前狀態並添加正確的遷移。

現在,我正在使用2個上下文文件處理單個項目,因此NuGet程序包管理器控制檯需要一種方法來識別此問題。

因此,下面的命令可以用來:

  1. 啓用特定上下文遷移:

    • `PM>啓用的遷移-ContextTypeName:-MigrationsDirectory:

這是一個我需要執行兩次的命令,每次執行一次XT。

然後,在我的AppServerSettings上下文的Seed方法,我會寫下面的代碼:

/// <summary> 
///  Runs after upgrading to the latest migration to allow seed data to be updated. 
/// </summary> 
/// <param name="context">Context to be used for updating seed data.</param> 
protected override void Seed(AppServerSettingsDataContext context) 
{ 
    // Creates the Member and assign all the settings which are required for the application to function. 
    context.Members.AddOrUpdate(x => x.Name, new Member("Povlo") 
    { 
     Settings = new List<MemberSettings> 
     { 
      new MemberSettings("DatabaseConnectionString", "Removed for Security Reasons"), 
     } 
    }); 

    // Make sure that for every member, the database is created by using the "MigrateDatabaseToLatestVersion" migration. 
    foreach (var setting in context.Members.Select(member => member.Settings.FirstOrDefault(x => x.Key == "DatabaseConnectionString"))) 
    { 
     using (var appServerContext = new AppServerDataContext(setting.Value)) 
     { 
      var de = new MigrateDatabaseToLatestVersion<AppServerDataContext, AppServer.Configuration>(); 
      de.InitializeDatabase(appServerContext); 

      appServerContext.Database.Initialize(true); 
     } 
    } 
} 

我在這裏做的基本上都是第一次創建與給定的連接字符串的成員(也可以是多個)。

然後,在同樣的方法中,我有一個foreach循環,它將根據數據庫中的連接字符串創建一個上下文。然後在這種情況下,數據庫正在升級到最新版本。

這樣做的好處是我使用的是代碼優先的方法,並且所有的數據庫都是最新的版本。

這樣做的缺點是所有模型都需要完全相同。