EF 6 code first - 从SQL server迁移到MySQL
最近鼓搗一個SaaS項目,后臺用的是entity framework 6 code first +SQL server,需要把數據庫遷移到MySQL,在這里記錄一下遇到的問題。時間比較久了記得不是很準確,供參考。
1, 以前殘留的Migration .cs文件(在項目的Migration目錄里,包括Configuration.cs)要統統刪除重新生成一遍,因為由SQL server connector生成的.cs文件與MySQL connector生成的.cs并不兼容。在nuget manager console里依次使用enable-migrations和add-migration <name>重新生成。
2,創建數據庫的時候報異常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."(或者是一個別的異常?記得不是很清楚),一番度娘之后發現要在DbContext的子類上添加以下:
[DbConfigurationType(typeof(MySqlEFConfiguration))]3,再次創建數據庫,又有異常Specified?key?was?too?long;?max?key?length?is?767 bytes,再一番度娘之后發現要在Configuration.cs文件里增加如下代碼:
SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());4,前進到建表的SQL語句,發現Procedure是MySQL的SQL語句的關鍵字,需要用`作為escape字符,而在SQL server里用的是[].
_helper.ExecuteCommand("INSERT INTO DBUpdateProcedure SET `Procedure` = @p0");5,開始遷移stored procedure。SQL server創建stored procedure是在migration cs文件里手動調用this.CreateStoredProcedure()實現的,但是MySQL創建stored procedure有一個很特殊的語法,需要先將DELIMETER設為別的東西(比如“//”),再結束的時候再設回來。這個東西通過Migration cs文件沒法實現,即使通過this.SQL()方法也不行,EF貌似不能正確的理解DELIMETER語法。所以只能在別的地方創建一個MySQLScript對象,通過設定它的Delimeter屬性來達到同樣的效果。
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遷移好了,在調用的時候又報異常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();這里我們必須構建MySqlParameter對象,而不是SQLParameter對象。并且MySql調用stored procedure要顯示的加CALL關鍵字,所以改正之后的代碼為:
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語句區數據轉化為對象的時候,報異常:System.FormatException occurred,?Message=String was not recognized as a valid Boolean.貌似因為實體類上有boolean屬性,MySQL connector生成的默認migration cs文件把這個屬性存在類型為tinyint的列里,但讀出來的時候又不知道怎么把0/1轉換為true/false,所以拋了這個異常。這個問題作為MySQL connector的一個bug報在了這里。就在快要絕望的時候,發現了stack overflow上牛人提的解決方案(原文),方法就是在modelbuilder里指定將boolean類型用bit列存儲,沒太明白,先記錄下來。
modelBuilder.Properties().Where(x => x.PropertyType == typeof(bool)).Configure(x => x.HasColumnType("bit"));?
這只是個開始,后面的坑再開新的隨筆記錄。
?
轉載于:https://www.cnblogs.com/KennethYip/p/4747914.html
總結
以上是生活随笔為你收集整理的EF 6 code first - 从SQL server迁移到MySQL的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 做梦梦到乌龟和龙虾怎么回事
- 下一篇: SQL常用语句|创建表,设置主键....