vos*_*d01 11 c# sql entity-framework ef-migrations entity-framework-5
我正在开始一个使用Entity Framework的新项目.我已经研究了如何创建数据库的选项,并发现Code-First Migrations最有意义(如果您需要知道原因,请参阅底部).Code-First Migrations让我可以下载到任意SQL,这意味着我仍然可以完全控制.在实践中,我发现问题是,对于某些常见任务而言,降低到SQL似乎非常重复.
出于我的目的,我并不关心迁移中的扩展是否与提供程序无关(我在内的SQL不是).但是,我并没有在迁移框架中找到一个好的接缝或扩展点来添加这些东西.
举一个具体的例子,假设我想为MS-SQL复制指定一个RowGuid列.每次出现都采取的形式
Sql(
string.Format(
"Alter Table {0} Alter Column {1} Add ROWGUIDCOL",
table,
column ));
Run Code Online (Sandbox Code Playgroud)
所以我编写静态方法来摆脱一些冗余
Sql( MigrationHelper.SetRowGuid( table, column );
Run Code Online (Sandbox Code Playgroud)
-要么-
MigrationHelper.SetRowGuid(Sql, table, column); //passing the Sql method
Run Code Online (Sandbox Code Playgroud)
可能可以在DbMigration上制作这些扩展方法中的任何一种,并通过它来访问它们this.
但仍然看起来不合适:
CreateTable(
"dbo.CustomerDirectory",
c => new
{
Uid = c.Int(nullable: false),
CustomerUid = c.Int(nullable: false),
Description = c.String(nullable: false, maxLength: 50, unicode: false),
RowGuid = c.Guid(nullable: false),
})
.PrimaryKey(t => t.Uid)
.ForeignKey("dbo.Customer", t => t.CustomerUid);
this.SetRowGuid( Sql, "dbo.CustomerDirectory", "RowGuid" );
//Custom method here because of desired naming convention of Constraint
this.SetDefaultConstraint( Sql, "dbo.CustomerDirectory", "''" ):
Run Code Online (Sandbox Code Playgroud)
它并不是非常糟糕,但对我来说仍然感觉像是一个黑客.我必须重复表名,我需要确保生成的列名正确.我发现表名需要重复很多,但列也是如此.然而,我真正想做的是添加到表声明中,恰好在表名和列名都已知的情况下.
但是,我找不到一个很好的扩展点来扩展流畅的界面,或者以一种感觉一致的方式扩展代码的第一次迁移.我错过了什么吗?有人找到了这样做的好方法吗?
关于为什么我处于这种情况的一些理由:
我不喜欢使用通用自定义属性解决方案来表示非映射数据库的常见解决方案,原因有几个,但最强烈的原因是它们不会被迁移自动获取意味着额外的维护.模型优先解决方案已经淘汰,因为它们无法完全控制数据库.数据库优先是因为控制而吸引人; 但是,它没有Code-First Migrations提供的开箱即用的更改管理功能.因此,Code-First Migrations似乎是一个赢家,因为[代码优先]模型驱动的更改是自动的,这意味着只有一件事需要维护.
虽然我不确定它是否好,但我找到了解决方案.我不得不在兔子洞的下方走得比我想要的更远,而且它不是一个真正的延伸点.
它允许我编写如下语句:
CreateTable(
"dbo.CustomerDirectory",
c => new
{
Uid = c.Int(nullable: false),
CustomerUid = c.Int(nullable: false),
Description = c.String(nullable: false, maxLength: 50, unicode: false),
RowGuid = c.Guid(nullable: false),
})
.PrimaryKey(t => t.Uid)
.ForeignKey("dbo.Customer", t => t.CustomerUid)
//SqlValue is a custom static helper class
.DefaultConstraint( t => t.Description, SqlValue.EmptyString)
//This is a convention in the project
//Equivalent to
// .DefaultConstraint( t => t.RowGuid, SqlValue.EmptyString)
// .RowGuid( t => t.RowGuid )
.StandardRowGuid()
//For one-offs
.Sql( tableName => string.Format( "ALTER TABLE {0} ...", tableName" );
Run Code Online (Sandbox Code Playgroud)
我不喜欢:
我只考虑在这里使用它,因为:
internal static class TableBuilderExtentions
{
internal static TableBuilder<TColumns> Sql<TColumns>(
this TableBuilder<TColumns> tableBuilder,
Func<string, string> sql,
bool suppressTransaction = false,
object anonymousArguments = null)
{
string sqlStatement = sql(tableBuilder.GetTableName());
DbMigration dbMigration = tableBuilder.GetDbMigration();
Action<string, bool, object> executeSql = dbMigration.GetSqlMethod();
executeSql(sqlStatement, suppressTransaction, anonymousArguments);
return tableBuilder;
}
[Pure]
private static DbMigration GetDbMigration<TColumns>(this TableBuilder<TColumns> tableBuilder)
{
var field = tableBuilder.GetType().GetField(
"_migration", BindingFlags.NonPublic | BindingFlags.Instance);
return (DbMigration)field.GetValue(tableBuilder);
}
/// <summary>
/// Caution: This implementation only works on single properties.
/// Also, coder may have specified the 'name' parameter which would make this invalid.
/// </summary>
private static string GetPropertyName<TColumns>(Expression<Func<TColumns, object>> someObject)
{
MemberExpression e = (MemberExpression)someObject.Body;
return e.Member.Name;
}
[Pure]
private static Action<string, bool, object> GetSqlMethod(this DbMigration migration)
{
MethodInfo methodInfo = typeof(DbMigration).GetMethod(
"Sql", BindingFlags.NonPublic | BindingFlags.Instance);
return (s, b, arg3) => methodInfo.Invoke(migration, new[] { s, b, arg3 });
}
[Pure]
private static string GetTableName<TColumns>(this TableBuilder<TColumns> tableBuilder)
{
var field = tableBuilder.GetType().GetField(
"_createTableOperation", BindingFlags.NonPublic | BindingFlags.Instance);
var createTableOperation = (CreateTableOperation)field.GetValue(tableBuilder);
return createTableOperation.Name;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2542 次 |
最近记录: |