EF 6 code first - 从SQL server迁移到MySQL
最近鼓搗一個(gè)SaaS項(xiàng)目,后臺(tái)用的是entity framework 6 code first +SQL server,需要把數(shù)據(jù)庫(kù)遷移到MySQL,在這里記錄一下遇到的問(wèn)題。時(shí)間比較久了記得不是很準(zhǔn)確,供參考。
1, 以前殘留的Migration .cs文件(在項(xiàng)目的Migration目錄里,包括Configuration.cs)要統(tǒng)統(tǒng)刪除重新生成一遍,因?yàn)橛蒘QL server connector生成的.cs文件與MySQL connector生成的.cs并不兼容。在nuget manager console里依次使用enable-migrations和add-migration <name>重新生成。
2,創(chuàng)建數(shù)據(jù)庫(kù)的時(shí)候報(bào)異常The ADO.NET provider with invariant name 'MySql.Data.MySqlClient' is either not registered in the machine or application config file, or could not be loaded. See the inner exception for details."(或者是一個(gè)別的異常?記得不是很清楚),一番度娘之后發(fā)現(xiàn)要在DbContext的子類(lèi)上添加以下:
[DbConfigurationType(typeof(MySqlEFConfiguration))]3,再次創(chuàng)建數(shù)據(jù)庫(kù),又有異常Specified?key?was?too?long;?max?key?length?is?767 bytes,再一番度娘之后發(fā)現(xiàn)要在Configuration.cs文件里增加如下代碼:
SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());4,前進(jìn)到建表的SQL語(yǔ)句,發(fā)現(xiàn)Procedure是MySQL的SQL語(yǔ)句的關(guān)鍵字,需要用`作為escape字符,而在SQL server里用的是[].
_helper.ExecuteCommand("INSERT INTO DBUpdateProcedure SET `Procedure` = @p0");5,開(kāi)始遷移stored procedure。SQL server創(chuàng)建stored procedure是在migration cs文件里手動(dòng)調(diào)用this.CreateStoredProcedure()實(shí)現(xiàn)的,但是MySQL創(chuàng)建stored procedure有一個(gè)很特殊的語(yǔ)法,需要先將DELIMETER設(shè)為別的東西(比如“//”),再結(jié)束的時(shí)候再設(shè)回來(lái)。這個(gè)東西通過(guò)Migration cs文件沒(méi)法實(shí)現(xiàn),即使通過(guò)this.SQL()方法也不行,EF貌似不能正確的理解DELIMETER語(yǔ)法。所以只能在別的地方創(chuàng)建一個(gè)MySQLScript對(duì)象,通過(guò)設(shè)定它的Delimeter屬性來(lái)達(dá)到同樣的效果。
sqlConn.Open();MySqlScript script_add_sp = new MySqlScript(sqlConn);StringBuilder sql = new StringBuilder();sql.Append(@"...");script_add_sp.Query = sql.ToString();script_add_sp.Delimiter = "//";script_add_sp.Execute();script_add_sp.Delimiter = ";";?
6,stored procedure遷移好了,在調(diào)用的時(shí)候又報(bào)異常Only MySqlParameter objects may be stored。原因是有如下代碼:
var tenantIdParam = new SqlParameter("TenantId", tenantId);var officeIdParam = new SqlParameter("OfficeId", officeId);var searchTextParam = new SqlParameter("SearchText", searchText ?? "");var pageIndexParam = new SqlParameter("PageIndex", pageIndex);var pageSizeParam = new SqlParameter("PageSize", pageSize);var orderFieldParam = new SqlParameter("OrderField", orderField);var patients = DataContext.Database.SqlQuery<PatientPageResult>("csp_SearchPatient(@TenantId, @OfficeId, @SearchText, @PageIndex, @PageSize, @OrderField)",tenantIdParam, officeIdParam, searchTextParam, pageIndexParam, pageSizeParam, orderFieldParam).ToList();這里我們必須構(gòu)建MySqlParameter對(duì)象,而不是SQLParameter對(duì)象。并且MySql調(diào)用stored procedure要顯示的加CALL關(guān)鍵字,所以改正之后的代碼為:
var tenantIdParam = new MySqlParameter("TenantId", tenantId);var officeIdParam = new MySqlParameter("OfficeId", officeId);var searchTextParam = new MySqlParameter("SearchText", searchText ?? "");var pageIndexParam = new MySqlParameter("PageIndex", pageIndex);var pageSizeParam = new MySqlParameter("PageSize", pageSize);var orderFieldParam = new MySqlParameter("OrderField", orderField);var patients = DataContext.Database.SqlQuery<PatientPageResult>("CALL csp_SearchPatient(@TenantId, @OfficeId, @SearchText, @PageIndex, @PageSize, @OrderField)",tenantIdParam, officeIdParam, searchTextParam, pageIndexParam, pageSizeParam, orderFieldParam).ToList();7,在Linq語(yǔ)句區(qū)數(shù)據(jù)轉(zhuǎn)化為對(duì)象的時(shí)候,報(bào)異常:System.FormatException occurred,?Message=String was not recognized as a valid Boolean.貌似因?yàn)閷?shí)體類(lèi)上有boolean屬性,MySQL connector生成的默認(rèn)migration cs文件把這個(gè)屬性存在類(lèi)型為tinyint的列里,但讀出來(lái)的時(shí)候又不知道怎么把0/1轉(zhuǎn)換為true/false,所以拋了這個(gè)異常。這個(gè)問(wèn)題作為MySQL connector的一個(gè)bug報(bào)在了這里。就在快要絕望的時(shí)候,發(fā)現(xiàn)了stack overflow上牛人提的解決方案(原文),方法就是在modelbuilder里指定將boolean類(lèi)型用bit列存儲(chǔ),沒(méi)太明白,先記錄下來(lái)。
modelBuilder.Properties().Where(x => x.PropertyType == typeof(bool)).Configure(x => x.HasColumnType("bit"));?
這只是個(gè)開(kāi)始,后面的坑再開(kāi)新的隨筆記錄。
?
轉(zhuǎn)載于:https://www.cnblogs.com/KennethYip/p/4747914.html
總結(jié)
以上是生活随笔為你收集整理的EF 6 code first - 从SQL server迁移到MySQL的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 做梦梦到乌龟和龙虾怎么回事
- 下一篇: JAVA运行程序代码段