所以我有一个由Entity框架进行大量迁移的应用程序。
我们希望立即获取所有迁移的脚本,并使用-Script
标记可以正常工作。
但是......它没有在SQL中添加GO
语句,给我们带来Alter view should be the first statement in a batch file...
我一直在搜索并手动添加Sql("GO");
这个问题的帮助,但仅整个脚本。当我再次使用包控制台管理器时,它会返回一个异常。
System.Data.SqlClient.SqlException (0x80131904): Could not find stored procedure 'GO'.
使用GO
代码时,有没有办法添加这些-Script
代码 ?
如果没有,对此有什么好处?
注意:我们也尝试过多个文件,但由于我们有很多迁移,所以每次都几乎无法维护。
答案 0 :(得分:15)
如果您尝试使用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')")
答案 1 :(得分: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");
}
}
然后添加Configuration
构造函数(在DbContext所在项目的Migrations
文件夹中),以便它使用这个新的sql生成器:
[...]
internal sealed class Configuration : DbMigrationsConfiguration<PMA.Dal.PmaContext>
{
public Configuration()
{
SetSqlGenerator("System.Data.SqlClient", new MigrationScriptBuilder());
AutomaticMigrationsEnabled = false;
}
[...]
现在,当您使用-Script标记生成脚本时,您可以看到insert into [__MigrationHistory]
被GO
或者,在您SqlServerMigrationSqlGenerator
的实施中,您可以覆盖脚本生成的任何部分,InsertHistoryOperation
适合我们。
答案 2 :(得分:10)
将SqlServerMigrationSqlGenerator
深处的概念作为Statement(sql, batchTerminator)
的可选参数存在。这是基于Skyp理念的东西。它在-script模式下都可以工作。 GO仅适用于不同于Skyp的操作,因为我们的需求略有不同。然后,您需要根据Skyp说明在Configuration
中注册此类。
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;
}
}
答案 3 :(得分:0)
最简单的方法是在GO语句之前添加/**/。
答案 4 :(得分:-2)
只需用.Replace替换当前语句(&#34; GO&#34;,&#34;&#34;);