1

我已经使用实体框架6和msyql数据库创建了一个新的.NET MVC 5 Web应用程序。我首先使用代码/模型。数据库服务器具有MyISAM的默认存储引擎,但我想要EF创建的表作为InnoDb。有谁知道是否有指定EF将在CREATE TABLE声明中使用的存储引擎的方式?强制引擎=使用实体框架代码时的innodb首先使用mysql

+0

你问如何修改迁移?您可以传递具有额外参数的匿名对象到] DbMigration.CreateTable](https://msdn.microsoft.com/zh-cn/library/system.data.entity.migrations.dbmigration.createtable(v = vs.113) .aspx),例如'new {SampleArgument =“MyValue”}'。也许你可以通过'new {Engine =“INNODB”}' –

+1

[@Devart](https://stackoverflow.com/users/135566/devart)的[dotConnect for MySQL](https://www.devart。 com/dotconnect/mysql /)提供了一个'MySqlCreateTableConfiguration'类,可以在Code-First Migrations的'CreateTable'操作中指定一个存储引擎。 – eggyal

回答

2

实际上,MySQL EF提供程序使用的引擎始终是InnoDB,如果不重写DDL生成器,您无法更改它。

尝试你可以创建一个简单的项目并启用MySQL日志。你会发现,每一个CREATE语句将终止与engine=InnoDb auto_increment=0

例如此类

public class Blog 
{ 
    public int BlogId { get; set; } 
    [MaxLength(200)] 
    public string Name { get; set; } 
    [MaxLength(200)] 
    public string Topic { get; set; } 
    public DateTime LastUpdated { get; set; } 

    [DefaultValue(0)] 
    public int Order { get; set; } 
    public virtual List<Post> Posts { get; set; } 
} 

与标准的MySQL EF提供商迁移,产生这个MySQL DDL语句

CREATE TABLE `Blogs` (
    `BlogId` INT NOT NULL auto_increment, 
    `Name` NVARCHAR(200), 
    `Topic` NVARCHAR(200), 
    `LastUpdated` DATETIME NOT NULL, 
    `Order` INT NOT NULL, 
    PRIMARY KEY (`BlogId`) 
    ) engine = InnoDb auto_increment = 0 

哪里是engine = InnoDb的?它在迁移源代码中很难编码。
你可以看看移植源代码 https://github.com/mysql/mysql-connector-net/blob/6.9/Source/MySql.Data.EntityFramework5/MySqlMigrationSqlGenerator.cs 方法MySqlMigrationSqlGenerator.Generate(CreateTableOperation op)。 最后的声明是sb.Append(") engine=InnoDb auto_increment=0");

所以,正确的问题应该是如何将引擎从InnoDB更改为另一个引擎。 可以继承MySqlMigrationSqlGenerator类和覆盖的方法,即:

internal class MyOwnMigrationSqlGenerator : MySqlMigrationSqlGenerator 
{ 

    public MyOwnMigrationSqlGenerator() 
    { 
     Engine = "InnoDB"; 
    } 

    public MyOwnMigrationSqlGenerator(string engine) 
    { 
     Engine = engine; 
    } 




    private readonly List<MigrationStatement> _specialStatements = new List<MigrationStatement>(); 

    public string Engine { get; set; } 

    public override IEnumerable<MigrationStatement> Generate(IEnumerable<MigrationOperation> migrationOperations, string providerManifestToken) 
    { 
     List<MigrationStatement> migrationStatements = base.Generate(migrationOperations, providerManifestToken).ToList(); 
     migrationStatements.AddRange(_specialStatements); 
     return migrationStatements; 
    } 

    protected override MigrationStatement Generate(CreateTableOperation op) 
    { 
     StringBuilder sb = new StringBuilder(); 
     string tableName = TrimSchemaPrefix(op.Name); 
     var autoIncrementCols = (List<string>)(typeof(MySqlMigrationSqlGenerator).GetProperty("autoIncrementCols", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this)); 
     var primaryKeyCols = (List<string>)(typeof(MySqlMigrationSqlGenerator).GetProperty("primaryKeyCols", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(this)); 


     sb.Append("create table " + "`" + tableName + "`" + " ("); 


     if (op.PrimaryKey != null) 
     { 
      op.PrimaryKey.Columns.ToList().ForEach(col => primaryKeyCols.Add(col)); 
     } 


     //columns 
     sb.Append(string.Join(",", op.Columns.Select(c => "`" + c.Name + "` " + Generate(c)))); 


     // Determine columns that are GUID & identity 
     List<ColumnModel> guidCols = new List<ColumnModel>(); 
     ColumnModel guidPk = null; 
     foreach (ColumnModel columnModel in op.Columns) 
     { 
      if (columnModel.Type == PrimitiveTypeKind.Guid && columnModel.IsIdentity && String.Compare(columnModel.StoreType, "CHAR(36) BINARY", true) == 0) 
      { 
       if (primaryKeyCols.Contains(columnModel.Name)) 
        guidPk = columnModel; 
       guidCols.Add(columnModel); 
      } 
     } 


     if (guidCols.Count != 0) 
     { 
      var createTrigger = new StringBuilder(); 
      createTrigger.AppendLine(string.Format("DROP TRIGGER IF EXISTS `{0}_IdentityTgr`;", TrimSchemaPrefix(tableName))); 
      createTrigger.AppendLine(string.Format("CREATE TRIGGER `{0}_IdentityTgr` BEFORE INSERT ON `{0}`", TrimSchemaPrefix(tableName))); 
      createTrigger.AppendLine("FOR EACH ROW BEGIN"); 
      foreach (ColumnModel opCol in guidCols) 
       createTrigger.AppendLine(string.Format("SET NEW.{0} = UUID();", opCol.Name)); 
      createTrigger.AppendLine(string.Format("DROP TEMPORARY TABLE IF EXISTS tmpIdentity_{0};", TrimSchemaPrefix(tableName))); 
      createTrigger.AppendLine(string.Format("CREATE TEMPORARY TABLE tmpIdentity_{0} (guid CHAR(36))ENGINE=MEMORY;", TrimSchemaPrefix(tableName))); 
      createTrigger.AppendLine(string.Format("INSERT INTO tmpIdentity_{0} VALUES(New.{1});", TrimSchemaPrefix(tableName), guidPk.Name)); 
      createTrigger.AppendLine("END"); 
      var sqlOp = new SqlOperation(createTrigger.ToString()); 
      _specialStatements.Add(Generate(sqlOp)); 
     } 


     if (op.PrimaryKey != null) // && !sb.ToString().Contains("primary key")) 
     { 
      sb.Append(","); 
      sb.Append("primary key (" + string.Join(",", op.PrimaryKey.Columns.Select(c => "`" + c + "`")) + ") "); 
     } 


     string keyFields = ","; 
     autoIncrementCols.ForEach(col => keyFields += (!primaryKeyCols.Contains(col) ? string.Format(" KEY (`{0}`),", col) : "")); 
     sb.Append(keyFields.Substring(0, keyFields.LastIndexOf(","))); 
     sb.Append(string.Format(") engine={0} auto_increment=0", Engine)); 

     return new MigrationStatement() { Sql = sb.ToString() }; 
    } 

    private string TrimSchemaPrefix(string table) 
    { 
     if (table.StartsWith("dbo.") || table.Contains("dbo.")) 
      return table.Replace("dbo.", ""); 


     return table; 
    } 

} 

然后,在你迁移配置,您可以指定自己的SQL生成。

internal sealed class MyContextMigrationConfiguration : DbMigrationsConfiguration<MyContext> 
{ 
    public MyContextMigrationConfiguration() 
    { 
     AutomaticMigrationsEnabled = true; 
     AutomaticMigrationDataLossAllowed = true; 
     SetSqlGenerator("MySql.Data.MySqlClient", new MyOwnMigrationSqlGenerator("MyPreferredEngine")); 
    } 

} 

编辑
有上MyOwnMigrationSqlGenerator类的错误。最好的办法是重写所有MySqlMigrationSqlGenerator。在这种情况下,我只修复访问MySqlMigrationSqlGenerator私有字段的类(这非常糟糕)。

相关问题