我已经使用实体框架6和msyql数据库创建了一个新的.NET MVC 5 Web应用程序。我首先使用代码/模型。数据库服务器具有MyISAM的默认存储引擎,但我想要EF创建的表作为InnoDb。有谁知道是否有指定EF将在CREATE TABLE声明中使用的存储引擎的方式?强制引擎=使用实体框架代码时的innodb首先使用mysql
1
A
回答
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私有字段的类(这非常糟糕)。
相关问题
- 1. 实体框架代码首先+ MySQL ... NullReferenceException
- 2. 使用实体框架代码的性能 - 首先
- 3. 实体框架代码优先使用
- 4. 我在实体框架代码首先
- 5. 实体框架代码首先愁楚
- 6. 实体框架代码首先FK场
- 7. 部署实体框架代码首先
- 8. 变化实体框架代码首先
- 9. 实体框架代码首先使用Where子句更新
- 10. 实体框架多很多使用代码首先
- 11. 使用实体框架代码首先获取InvalidOperationException
- 12. 如何首先在实体框架代码中使用MigratorScriptingDecorator?
- 13. 首先使用实体框架代码保存单个EntityObject
- 14. 实体框架代码首先对伪索引使用存储过程?
- 15. 首先使用实体框架代码实现存储库的通用方法
- 16. 首先添加带实体框架代码的索引(CTP5)
- 17. 如何制作实体框架代码首先使用SQL Azure DB?
- 18. 实体框架代码优先 - 使用MySql创建数据库?
- 19. 使用MySql实体框架4和代码优先开发CTP
- 20. 使用实体框架代码首先使用动态连接字符串
- 21. 使用实体框架代码时首先处理相关数据
- 22. 使用实体框架模型加密密码字段首先
- 23. 实体框架代码首先忽略连接字符串,使用IIS代替
- 24. 实体框架代码首先不可用
- 25. 用实体框架更新数据库模式代码首先
- 26. 实体框架代码首先用于Oracle
- 27. 使用实体框架强制ICollection <>中的一个或多个代码首先
- 28. 首先使用TransactionScope与实体框架代码和通用提供商
- 29. 首先使用实体框架代码与结点表的一对多关系
- 30. 如何我使用实体框架5映射在实体框架代码首先
你问如何修改迁移?您可以传递具有额外参数的匿名对象到] 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”}' –
[@Devart](https://stackoverflow.com/users/135566/devart)的[dotConnect for MySQL](https://www.devart。 com/dotconnect/mysql /)提供了一个'MySqlCreateTableConfiguration'类,可以在Code-First Migrations的'CreateTable'操作中指定一个存储引擎。 – eggyal