早期 Entity Framework (EF) 官方僅支援 SQL Server,MySQL 需第三方 Provider。本文記錄從 MySQL 官方原始碼 (MySql.Data 5.3.0 + MySql.Data.Entity) 自行編譯、簽名、註冊 EF Provider 的完整流程,解決專案必須使用 MySQL 且預算有限無法購買商業版 Devart dotConnect 的實際需求。
MySql.Data (5.3.0) 與新增的 MySql.Data.Entity 專案MySql.Data 並**強名簽名** (sn -k key.snk → 專案屬性 → 簽署)MySql.Data.Entity 並參考剛簽名的 MySql.Data,同樣強名簽名MySql.Data.Entity 的 PublicKeyToken (sn -T MySql.Data.Entity.dll)編輯 MySqlClientFactory 的 IServiceProvider.GetService,指向自建的 Provider 實作:
private FieldInfo MySqlDbProviderServicesInstance {
get {
if (mySqlDbProviderServicesInstance == null) {
string fullName = "MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity, Version=5.3.0.0, Culture=neutral, PublicKeyToken=b3fe30829fc170e4";
Type providerServicesType = Type.GetType(fullName, false);
mySqlDbProviderServicesInstance = providerServicesType.GetField("Instance",
BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
}
return mySqlDbProviderServicesInstance;
}
}
object IServiceProvider.GetService(Type serviceType) {
if (serviceType != DbServicesType) return null;
if (MySqlDbProviderServicesInstance == null) return null;
return MySqlDbProviderServicesInstance.GetValue(null);
}
關鍵:PublicKeyToken 必須與剛編譯的 MySql.Data.Entity 組件完全一致。
MySql.Data.dll 與 MySql.Data.Entity.dllgacutil /i MySql.Data.dll、gacutil /i MySql.Data.Entity.dll編輯 machine.config (通常在 %windir%\Microsoft.NET\Framework\v4.0.30319\Config\),在 <system.data><DbProviderFactories> 區段加入:
<add name="MySQL Data Provider"
invariant="MySql.Data.MySqlClient"
description=".Net Framework Data Provider for MySQL"
type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=5.3.0.0, Culture=neutral, PublicKeyToken=c66bfea3ae91850d" />
注意:此處 PublicKeyToken 必須對應 MySql.Data (非 Entity 組件)。
CREATE TABLE `mytable` (
`ID` int(11) NOT NULL DEFAULT '0',
`NAME` varchar(100) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
<Schema Namespace="TestModel.Store" Provider="MySql.Data.MySqlClient" ProviderManifestToken="MySQL" ...>
<EntityContainer Name="Model3TargetContainer">
<EntitySet Name="MYTABLE" EntityType="TestModel.Store.MYTABLE" store:Type="Tables" Schema="testdb" />
</EntityContainer>
<EntityType Name="MYTABLE">
<Key><PropertyRef Name="ID" /></Key>
<Property Name="ID" Type="int" Nullable="false" />
<Property Name="NAME" Type="varchar" Nullable="true" MaxLength="40" />
</EntityType>
</Schema>
概念模型使用 Company 實體 (屬性 ID, Name),MSL 將 Company.Name 對應至資料表 NAME 欄位,Company.ID 對應 ID。
edmgen /mode:EntityClassGeneration /incsdl:TestDB.csdl /namespace:Test /project:Test
using (var db = new Model3Container1(GetConnectionString())) {
var coms = from c in db.Company where c.ID < 50 select c;
foreach (var item in coms) Console.WriteLine(item.Name);
}
private static string GetConnectionString() {
return $"metadata=TestDB.csdl|TestDB.msl|TestDB.ssdl;provider=MySql.Data.MySqlClient;provider connection string=\"User Id=root;Password=root;Host=192.168.1.152;Database=testdb;Persist Security Info=True\"";
}
文末提供編譯完成的兩個 DLL 下載連結供參考測試。