ADO.NET Entityframework MYSQL provider

     接触ADO.NET Entityframework有一段时间了,在实际项目的应用中有一个最大的问题就是M$没有对多种数据库提供支持,在笔者最近碰到的一个网站项目中,公司要求使用MYSQL,到处找MYSQL的EFProvider,发现Devart dotConnect还不错,提供了比较完善的解决方案,只是在自动从数据库提取物理模型中存在编码的问题,到目前还没有找到解决办法,但是Devart dotConnect是收费的,专业版得上千美刀,有Free Edition,但是不提供对EntityFramwork的支持。无奈,寻找其他的解决方案。

     偶然间在一份SUN的文档中有提到在未来版本中对AEF的支持,到MYSQL.com下载最新的MySql.Data.dll为5.2.5版,并没有对AEF提供支持,再到源码服务器,惊喜得看到多了一个MySql.Data.Entity项目,MySql.Data也已经到了5.3.0版。立刻下载。

     下载后先编译MySQL.Data,并签名程序集,MySQL.Data.Entity引用MySQL.Data,编译并签名,取得MySQL.Data.Entity的PublicKeyToken,修改MySQL.Data中类MySqlClientFactory的IServiceProvider.GetService方法相关的代码,将Provider类型指向刚才编译好的MySQL.Data.Entity程序集中的MySql.Data.MySqlClient.MySqlProviderServices类,修改后大概就像下面的样子。

ContractedBlock.gif ExpandedBlockStart.gif Code
        private FieldInfo MySqlDbProviderServicesInstance
        {
            
get
            {
                
if (mySqlDbProviderServicesInstance == null)
                {
                    
//string fullName = Assembly.GetExecutingAssembly().FullName;
                    
//fullName = fullName.Replace("MySql.Data", "MySql.Data.Entity");
                    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)
        {
            
// DbProviderServices is the only service we offer up right now
            if (serviceType != DbServicesType) return null;

            
if (MySqlDbProviderServicesInstance == nullreturn null;

            
return MySqlDbProviderServicesInstance.GetValue(null);
        }

     

     注意PublicKeyToken的值,要和MySQL.Data.Entity程序集对应。OK,再重新编译得到MySQL.Data.dll和MySQL.Data.Entity.dll。

     将这两个文件安装进GAC中。

     接下来注册我们的provider,打开machine.config,在system.data/DbProviderFactories节点中,添加下面的元素:

ContractedBlock.gif ExpandedBlockStart.gif Code
    <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程序集的PublicKeyToken一致。

     这样,在我们的程序中就可以使用AEF for MySQL了,测试一下。

     建立测试库和测试表:

ContractedBlock.gif ExpandedBlockStart.gif Code
CREATE TABLE `mytable` (`ID` int(11NOT NULL default '0',`NAME` varchar(100default NULL,PRIMARY KEY  (`ID`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;

 

     对立对应的物理模型TestDB.ssdl:

ContractedBlock.gif ExpandedBlockStart.gif Code
<?xml version="1.0" encoding="utf-8"?>
<Schema Namespace="TestModel.Store" Alias="Self" Provider="MySql.Data.MySqlClient" ProviderManifestToken="MySQL" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl">
  
<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>

 

     概念模型:TestDB.csdl

ContractedBlock.gif ExpandedBlockStart.gif Code
<?xml version="1.0" encoding="utf-8"?>
<Schema xmlns="http://schemas.microsoft.com/ado/2006/04/edm" Namespace="Model3" Alias="Self">
  
<EntityContainer Name="Model3Container1" >
    
<EntitySet Name="Company" EntityType="Model3.Company" />
  
</EntityContainer>
  
<EntityType Name="Company">
    
<Key>
      
<PropertyRef Name="ID" />
    
</Key>
    
<Property Name="ID" Type="Int32" Nullable="false" />
    
<Property Name="Name" Type="String" Nullable="true" />
  
</EntityType>
</Schema>

 

     以及映射文件:TestDB.msl

ContractedBlock.gif ExpandedBlockStart.gif Code
<?xml version="1.0" encoding="utf-8"?>
<Mapping xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS" Space="C-S">
  
<Alias Key="Model" Value="Model3" />
  
<Alias Key="Target" Value="Model3.Target" />
  
<EntityContainerMapping CdmEntityContainer="Model3Container1" StorageEntityContainer="Model3TargetContainer">
    
<EntitySetMapping Name="Company">
      
<EntityTypeMapping TypeName="IsTypeOf(Model3.Company)">
        
<MappingFragment StoreEntitySet="MYTABLE">
          
<ScalarProperty Name="Name" ColumnName="NAME" />
          
<ScalarProperty Name="ID" ColumnName="ID" />
        
</MappingFragment>
      
</EntityTypeMapping>
    
</EntitySetMapping>
  
</EntityContainerMapping>
</Mapping>

 

     这样模型配置就完成了,我这里概念模型和物理模型中的字段名和属性名是不同的。

     为了能以实体类的方式操作数据库,利用下面的命令自动生成实体类文件:

     edmgen /mode:EntityClassGeneration /incsdl:TestDB.csdl /namespace:Test /project:Test

     把生成的文件包含到项目中,测试代码如下:

ContractedBlock.gif ExpandedBlockStart.gif Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.Entity;

namespace MySql.Data.Entity.Tests
{
    
class programe
    {
        
static void Main()
        {

            
using (Model3.Model3Container1 db = new Model3.Model3Container1(GetConnectionString()))
            {

                var coms 
= from com in db.Company
                           
where com.ID < 50
                           select com;

                
foreach (var item in coms)
                {
                    Console.WriteLine(item.Name);
                }

            }

            Console.Read();
        }

        
private static string GetConnectionString()
        {
            
return String.Format(
                
"metadata=TestDB.csdl|TestDB.msl|TestDB.ssdl;provider=MySql.Data.MySqlClient; provider connection string=\"{0}\""
                , 
"User Id=root;Password=root;Host=192.168.1.152;Database=testdb;Persist Security Info=True");
        }

    }
}

 

     到这里为止已经能够正常读取出数据,但是由于该组件还未正式发布,笔者也未进行详细的测试,稳定性、可靠性可能存在一定问题,希望有兴趣的朋友一起研究和学习,对在项目中急需使用AEF for MySQL的朋友能有所帮助。

     最后提供两个DLL文件的下载:AEF for MYSQL

posted on 2009-01-09 12:46  钧梓昊逑 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/wisdomqq/archive/2009/01/09/1372136.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值