讓Entity framework支援多資料庫
羅朝輝 (http://kesalin.cnblogs.com/)
本文遵循“署名-非商業用途-保持一致”創作公用協議
EF對Sql Server的支援非常好,無論是Code First,還是 Model First 還是 Database First 都支援的很好,但是對非微軟係數據庫的支援就不那麼友好了,現在唯一能保證的是對大部分資料庫的 Database First 支援的很好。所以在這裡,我們讓 Entity framework 支援多資料庫實現的思路就是基於 Database First 的。首先在各資料庫中建立好資料庫表(這裡有很多講究的地府,欄位類型必須一致,可以使用Power Designer工具來簡化手工勞動),再基於某一資料庫產生概念性模型,儲存模型以及映射關係,然後拷貝產生的儲存模型檔案並修改,使之能與其他資料庫匹配起來,從而獲得對多資料庫的支援。
本樣本示範了對Sql Server 2008和MySQL 5.5兩種書庫的支援,使用的 MySQL Connector Net 6.3.5。請參考前文安裝相關的軟體。下面講述具體步驟:
1,分別在 Sql Server 2008 和 MySQL 5.5 建立資料庫 school及表 student(推薦使用小寫,MySQL預設使用小寫),student表只包含三個欄位:Id(主鍵),Name 和 Age。請注意兩個表的資料類型必須完全一致!
Sql Server 2008表:
MySql 表:
2,然後分別在兩個表中插入不同的測試資料,也可以在代碼中寫插入資料,這裡為了簡化,直接使用資料庫管理工具插入測試資料。
3,建立C#控制台程式 EFMutilpleDatabase:
4,右擊項目名,向其中添加類型為ADO.NET Entity Data Model的新Item:StudentModel.edmx:
選擇從資料庫產生:
然後建立 Connection,首先我們使用 MySQL資料庫,設定串連到MySQL的Connection,資料庫表選擇 school,這樣嚮導就會自動為我們產生概念性模型,儲存模型以及映射關係,connection string等:
選擇需要用到的資料庫表:
5,至此嚮導工作完成,我們先來看看嚮導為我們產生的檔案:
App.Config:資料庫連接相關的配置;
StudentModel.edmx:概念性模型,儲存模型,映射關係等都自動產生在該檔案中;
StudentModel.Designer.cs:自動產生的程式碼,通過這些自動產生的資料對象類,我們就可以直接操作資料庫。
6,為了方便後面支援多資料庫,我們現在在App.Config檔案中修改預設 connection string的名字為:schoolEntitiesMySQL。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="schoolEntitiesMySQL" connectionString="metadata=res://*/StudentModel.csdl|res://*/StudentModel.ssdl|res://*/StudentModel.msl;provider=MySql.Data.MySqlClient;provider connection string="server=localhost;User Id=root;password=yourpwd;Persist Security Info=True;database=school"" providerName="System.Data.EntityClient" />
</connectionStrings>
</configuration>
7,下面我們來編寫測試與MySQL的串連的代碼。相工程中添加 reference:System.Configuration,然後修改 Program.cs為:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.Objects;
using System.Configuration;
namespace EFMultipleDatabase
{
class Program
{
private static void ProcessDatabase(string connectionStringName)
{
string connectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
using (var queryContext = new schoolEntities(connectionString))
{
Console.WriteLine(">> All Student:");
queryContext.Connection.Open();
// Query
//
using (var transaction = queryContext.Connection.BeginTransaction())
{
var people = from p in queryContext.student orderby p.Age select p;
foreach (var p in people)
{
Console.WriteLine(" {0}, Age: {1}", p.Name, p.Age);
}
transaction.Commit();
}
queryContext.Dispose();
}
}
static void Main(string[] args)
{
Console.WriteLine(" ========MySQL=====");
ProcessDatabase("schoolEntitiesMySQL");
Console.ReadLine();
}
}
}
在上面的代碼中,我們是根據讀取 App.Config 中的 connection string 配置來決定串連到哪一個資料庫的,這樣的設計方便我們添加與其他資料庫連接配置,以支援多種資料庫。
8,下面我們來讓程式支援 Sql Server 2008。首先,需要手動建立儲存模型檔案,在項目中建立名為StudentModel.SqlServer.ssdl 的xml檔案。然後右擊StudentModel.edmx選擇 Open With XML(Text) Editor,將<!-- SSDL content -->之後介於 <edmx:StorageModels> … </edmx:StorageModels>之間的內容拷貝至建立的StudentModel.SqlServer.ssdl檔案中,這樣StudentModel.SqlServer.ssdl的內容應該如下:
<?xml version="1.0" encoding="utf-8" ?>
<Schema Namespace="schoolModel.Store" Alias="Self" Provider="MySql.Data.MySqlClient" ProviderManifestToken="5.1" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
<EntityContainer Name="schoolModelStoreContainer">
<EntitySet Name="student" EntityType="schoolModel.Store.student" store:Type="Tables" Schema="school" />
</EntityContainer>
<EntityType Name="student">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
<Property Name="Name" Type="varchar" MaxLength="45" />
<Property Name="Age" Type="umediumint" />
</EntityType>
</Schema>
9,緊接著我們來修改 StudentModel.SqlServer.ssdl 儲存模型檔案,使之能與匹配Sql Server 2008資料庫表。首先我們需要將 Provider 和 ProviderManifestToken修改為:
Provider="System.Data.SqlClient" ProviderManifestToken="2008"
這表示該儲存模型是基於 Sql Server 2008 資料庫的。然後將各個欄位的 Type 修改為Sql Server 2008支援的資料類型(MySQL使用的資料類型肯定不會與Sql Server 2008完全相同),並將該儲存模型放到輸出目錄下,修改該檔案的屬性 Copy to Output Directory 為 Copy Always。。修改之後的內容應如下:
<?xml version="1.0" encoding="utf-8" ?>
<Schema Namespace="schoolModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
<EntityContainer Name="schoolModelStoreContainer">
<EntitySet Name="student" EntityType="schoolModel.Store.student" store:Type="Tables" Schema="dbo" />
</EntityContainer>
<EntityType Name="student">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="int" Nullable="false"/>
<Property Name="Name" Type="nchar" MaxLength="45" />
<Property Name="Age" Type="int" />
</EntityType>
</Schema>
10,這樣我們就完成了對儲存模型的修改,下面我們來在App.config中增加對Sql Server 2008資料庫的串連 string。以下是修改之後的App.config:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="schoolEntitiesMySQL" connectionString="metadata=res://*/StudentModel.csdl|res://*/StudentModel.ssdl|res://*/StudentModel.msl;provider=MySql.Data.MySqlClient;provider connection string="server=localhost;User Id=root;password=yourpwd;Persist Security Info=True;database=school"" providerName="System.Data.EntityClient" />
<add name="schoolEntitiesSqlServer" connectionString="metadata=res://*/StudentModel.csdl|StudentModel.SqlServer.ssdl|res://*/StudentModel.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=school;persist security info=True;user id=sa;password=
yourpwd
;multipleactiveresultsets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
</connectionStrings>
</configuration>
11,至此配置工作完成,我們只需在 main()中調用如下語句即可測試與Sql Server 2008資料庫的串連:
static void Main(string[] args)
{
Console.WriteLine(" ========MySQL=====");
ProcessDatabase("schoolEntitiesMySQL");
Console.WriteLine(" ========SQL Server 2008=====");
ProcessDatabase("schoolEntitiesSqlServer");
Console.ReadLine();
}
編譯運行,結果如下:
總結:
上面的過程是先產生一致的資料庫表,然後通過某種資料庫產生概念性模型,儲存模型以及映射關係,然後拷貝並修改儲存模型,使之與其他資料庫匹配,從而完成對多資料庫的支援。