·您现在的位置: 云翼网络 >> 文章中心 >> 网站建设 >> 网站建设开发 >> ASP.NET网站开发 >> 将SQL SERVER数据库改成MySql

将SQL SERVER数据库改成MySql

作者:佚名      ASP.NET网站开发编辑:admin      更新时间:2022-07-23

将SQL SERVER数据库改成MySQL

(www.helpqy.com) 架构在阿里云上,最先想采用SQL SERVER,想大家都是微软家族的嘛。但是发现SQL SERVER需要的配置比较高,需要的银子也比较多,最后在纠结之下换成了MySql。由于整个网站基于微软的asp.net MVC架构,同时基于EF6.0,而MVC架构默认采用了SQL SERVER,这里又与code first混合在一起,所以在修改和过渡过程中还是遇到了不少问题。这个过程中参考了博客园不少前辈的文章,真是太感谢了。其中主要参考的一篇外文是:“ASP.NET Identity: Using MySQL Storage with an EntityFramework MySQL PRovider (C#)”。时间太长了,现在在总结和回忆,可能还是会遗漏掉一些细节,请各位,也请我自己谅解哈,嘿嘿。

1. 通过NuGet下载Mysql的provider,以便EF能够连接Mysql数据库。下载MySql.Data.Entity包时,会有两个包被集成进工程,如下所示:

2. 然后是Web.config的修改。

在connectionStrings中去掉SQL SERVER相关的连接字符串,加入mysql的连接字符串,如下所示:

1 <connectionStrings>   2     <add name="ConnectionName" 3          providerName="MySql.Data.MySqlClient"               connectionString="Server=xxx.xxx.xxx.xxx;Uid=xxx;Pwd=xxx;Database=xxxxx" />  4   </connectionStrings>

在providers中加入mysql的provider信息:

<providers>      <provider invariantName="MySql.Data.MySqlClient"                 type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6" />      </providers>

在system.data中加入mysql的factory信息:

<system.data>    <DbProviderFactories>         <remove invariant="MySql.Data.MySqlClient"></remove>         <add name="MySQL Data Provider"            invariant="MySql.Data.MySqlClient"           description=".Net Framework Data Provider for MySQL"           type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.8.3.0, Culture=neutral, PublicKeyToken=xxxx" />    </DbProviderFactories></system.data>

3. 加入定制化的MigrationHistory context。这一节非常重要,重点参考了上述的那篇美文。

EF的Code First采用Migration History表来保证model和数据库的一致性。但是数据库换成Mysql后默认的主键长度超过了Mysql最大允许的767字节,所以必须修改主键长度,这里需要修改HistoryContext,可以新增加一个类来继承HistoryContext,如下所示:

 1 public class MySqlHistoryContext : HistoryContext 2     { 3         public MySqlHistoryContext( 4             DbConnection existingConnection, 5             string defaultSchema) 6             : base(existingConnection, defaultSchema) 7         { } 8  9         protected override void OnModelCreating(DbModelBuilder modelBuilder)10         {11             base.OnModelCreating(modelBuilder);12             modelBuilder.Entity<HistoryRow>().Property(h => h.MigrationId).HasMaxLength(100).IsRequired();13             modelBuilder.Entity<HistoryRow>().Property(h => h.ContextKey).HasMaxLength(200).IsRequired();14         }15     }

为了让EF使用修改后的HistoryContext,而不使用默认的HistoryContext,则需要增加类修改DbConfiguration:

1 public class MySqlConfiguration : DbConfiguration2     {3         public MySqlConfiguration()4         {5             SetHistoryContext("MySql.Data.MySqlClient", (conn, schema) => new MySqlHistoryContext(conn, schema));6         }7     }

4. MySql provider无法直接支持EF的migration和code first,需要增加一个定制化的EF initializer:

 1 public class MySqlInitializer : IDatabaseInitializer<applicationDbContext> 2     { 3         public void InitializeDatabase(ApplicationDbContext context) 4         { 5             if (!context.Database.Exists()) 6             { 7                 context.Database.Create(); 8             } 9             else10             {11                 var migrationHistoryTableExists = ((IObjectContextAdapter)context).ObjectContext.ExecuteStoreQuery<int>(12                     string.Format(13                     "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '{0}' AND table_name = '__MigrationHistory'",14                     "XXX数据库名"15                     ));16 17                 if (migrationHistoryTableExists.FirstOrDefault() == 0)18                 {19                     context.Database.Delete();20                     context.Database.Create();21                 }22             }23         }24     }

同时需要在DbContext中使用此定制化的initializer:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>    {        static ApplicationDbContext()        {            Database.SetInitializer(new MySqlInitializer());        }        public virtual DbSet<xxxx> xxxx { get; set; }        public ApplicationDbContext()            : base("xxxx连接名")        {        }    }