Tik*_*kes 14 sql entity-framework ef-migrations
所以我有一个由Entity框架进行大量迁移的应用程序.我们希望立即获取所有迁移的脚本,并且使用该-Script标记可以正常工作.
但是......它没有GO在SQL中添加语句,给我们带来了类似的问题Alter view should be the first statement in a batch file...
我一直在搜索并手动添加Sql("GO");有关此问题的帮助,但仅针对整个脚本.当我再次使用包控制台管理器时,它返回一个异常.
System.Data.SqlClient.SqlException (0x80131904): Could not find stored procedure 'GO'.
Run Code Online (Sandbox Code Playgroud)
有没有办法添加这些GO标签仅使用时-Script的标签?如果没有,对此有什么好处?
注意:我们也尝试过多个文件,但由于我们有很多迁移,所以每次都几乎无法维护.
Col*_*lin 17
如果您尝试使用更改视图Sql("Alter View dbo.Foos As etc"),则可以通过将sql放在命令中来避免should be the first statement in a batch file错误而不添加GO语句EXEC:
Sql("EXEC('Alter View dbo.Foos As etc')")
Sky*_*kyp 11
为了更改由实体框架迁移生成的SQL,您可以创建一个新的 SqlServerMigrationSqlGenerator
我们这样做是为了在迁移历史记录之前和之后添加GO语句:
public class MigrationScriptBuilder: SqlServerMigrationSqlGenerator
{
protected override void Generate(System.Data.Entity.Migrations.Model.InsertHistoryOperation insertHistoryOperation)
{
Statement("GO");
base.Generate(insertHistoryOperation);
Statement("GO");
}
}
Run Code Online (Sandbox Code Playgroud)
然后添加Configuration构造函数(在MigrationsDbContext所在的项目的 文件夹中),以便它使用这个新的sql生成器:
[...]
internal sealed class Configuration : DbMigrationsConfiguration<PMA.Dal.PmaContext>
{
public Configuration()
{
SetSqlGenerator("System.Data.SqlClient", new MigrationScriptBuilder());
AutomaticMigrationsEnabled = false;
}
[...]
Run Code Online (Sandbox Code Playgroud)
因此,现在当您使用-Script标记生成脚本时,您可以看到它insert into [__MigrationHistory]被包围GO
或者在您的实现中,SqlServerMigrationSqlGenerator您可以覆盖脚本生成的任何部分,这InsertHistoryOperation适合我们.
Yep*_*kai 10
结果概念存在于SqlServerMigrationSqlGenerator作为可选参数的深处Statement(sql, batchTerminator).这是基于Skyp理念的东西.它在-script模式下都可以工作.GO仅适用于不同于Skyp的操作,因为我们的需求略有不同.然后,您需要Configuration按照Skyp说明注册此类.
public class MigrationScriptBuilder : SqlServerMigrationSqlGenerator
{
private string Marker = Guid.NewGuid().ToString(); //To cheat on the check null or empty of the base generator
protected override void Generate(AlterProcedureOperation alterProcedureOperation)
{
SqlGo();
base.Generate(alterProcedureOperation);
SqlGo();
}
protected override void Generate(CreateProcedureOperation createProcedureOperation)
{
SqlGo();
base.Generate(createProcedureOperation);
SqlGo();
}
protected override void Generate(SqlOperation sqlOperation)
{
SqlGo();
base.Generate(sqlOperation);
}
private void SqlGo()
{
Statement(Marker, batchTerminator: "GO");
}
public override IEnumerable<MigrationStatement> Generate(IEnumerable<MigrationOperation> migrationOperations, string providerManifestToken)
{
var result = new List<MigrationStatement>();
var statements = base.Generate(migrationOperations, providerManifestToken);
bool pendingBatchTerminator = false;
foreach (var item in statements)
{
if(item.Sql == Marker && item.BatchTerminator == "GO")
{
pendingBatchTerminator = true;
}
else
{
if(pendingBatchTerminator)
{
item.BatchTerminator = "GO";
pendingBatchTerminator = false;
}
result.Add(item);
}
}
return result;
}
}
Run Code Online (Sandbox Code Playgroud)