2013-06-14 17 views
10

Vì vậy, tôi có một ứng dụng có rất nhiều di chuyển được thực hiện bởi khung Entity. Chúng tôi muốn nhận một kịch bản cho tất cả các di chuyển cùng một lúc và sử dụng thẻ -Script hoạt động tốt.Thêm câu lệnh 'GO' vào di chuyển Khung thực thể

Tuy nhiên ... nó không thêm GO báo cáo trong SQL cho chúng tôi các vấn đề như Alter view should be the first statement in a batch file...

Tôi đã tìm kiếm xung quanh và tự thêm Sql("GO"); giúp đỡ với vấn đề này nhưng chỉ cho toàn bộ kịch bản. Khi tôi sử dụng trình quản lý bàn điều khiển gói một lần nữa nó trả về một ngoại lệ.

System.Data.SqlClient.SqlException (0x80131904): Could not find stored procedure 'GO'. 

Có cách nào để thêm những GO thẻ chỉ khi sử dụng thẻ -Script? Nếu không, cách tiếp cận tốt cho điều này là gì?

Lưu ý: chúng tôi cũng đã thử có nhiều tệp nhưng vì chúng tôi có quá nhiều lần di chuyển, điều này gần như không thể duy trì mỗi lần.

Trả lời

10

Để thay đổi SQL được tạo ra bởi sự di cư của khuôn khổ tổ chức bạn có thể tạo mới SqlServerMigrationSqlGenerator

Chúng tôi đã làm điều này để thêm một tuyên bố GO trước và sau khi lịch sử di cư:

public class MigrationScriptBuilder: SqlServerMigrationSqlGenerator 
{ 
    protected override void Generate(System.Data.Entity.Migrations.Model.InsertHistoryOperation insertHistoryOperation) 
    { 
     Statement("GO"); 

     base.Generate(insertHistoryOperation); 

     Statement("GO"); 

    } 
} 

sau đó thêm trong nhà xây dựng Configuration (trong thư mục Migrations của dự án nơi bạn DbContext là) để nó sử dụng trình tạo sql mới này:

[...] 
internal sealed class Configuration : DbMigrationsConfiguration<PMA.Dal.PmaContext> 
{ 
    public Configuration() 
    { 
     SetSqlGenerator("System.Data.SqlClient", new MigrationScriptBuilder()); 
     AutomaticMigrationsEnabled = false; 
    } 
[...] 

Vì vậy, bây giờ khi bạn tạo ra một kịch bản sử dụng thẻ -Script, bạn có thể thấy rằng insert into [__MigrationHistory] được bao quanh bởi GO

Ngoài ra trong việc thực hiện lại SqlServerMigrationSqlGenerator bạn có thể ghi đè lên bất kỳ phần nào của thế hệ kịch bản, InsertHistoryOperation là thích hợp cho chúng tôi.

+2

Hoạt động hoàn hảo khi sử dụng thẻ '-Script'. Tôi phải bình luận ra dòng 'SetSqlGenerator (" ..... 'tuy nhiên khi tôi không sử dụng nó bởi vì nếu không tôi có ngoại lệ một lần nữa. Điều này tuy nhiên tôi tiết kiệm rất nhiều thời gian vì nó chỉ là bình luận ra một dòng thay vì thêm 'Sql (" GO ");' ở khắp mọi nơi. Cảm ơn! – Tikkes

+0

Tôi không thể tìm thấy InsertHistoryOperation.Lắp ráp là nó trong? –

+3

Ah Tôi nghĩ rằng nó được đổi tên thành EF 6 thành HistoryOperation –

13

Nếu bạn đang cố gắng để thay đổi cái nhìn của bạn sử dụng Sql('Alter View dbo.Foos As etc'), sau đó bạn có thể tránh được những lỗi should be the first statement in a batch file mà không cần thêm GO báo cáo bằng cách đặt sql bên trong một lệnh EXEC:

Sql(EXEC('Alter View dbo.Foos As etc'))

+0

Điều này cho phép điền vào các bảng và cột ngay sau khi tạo. Tuyệt quá! – blazkovicz

+0

WOW, điều đó thực sự đơn giản và hoạt động! cảm ơn vì điều đó! – trailmax

+0

Anwers tốt nhất, cảm ơn !! – ArDumez

-2

Chỉ cần thay thế báo cáo kết quả hiện tại với a .Replace ("GO", "");

8

Tắt khái niệm tồn tại sâu trong SqlServerMigrationSqlGenerator làm đối số tùy chọn cho Statement(sql, batchTerminator). Đây là một cái gì đó dựa trên ý tưởng Skyp. Nó hoạt động ở cả chế độ in -cript hay không. GOs là cho các hoạt động khác nhau hơn cho Skyp chỉ vì nhu cầu của chúng tôi là một chút khác nhau. Sau đó bạn cần đăng ký lớp học này theo số Configuration theo hướng dẫn của 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; 
     } 
    } 
+1

Điều này làm việc cho tôi! Tôi đã tìm kiếm một cách mà làm việc cả hai có và không có đối số -script. Cảm ơn! – ravinsp

+0

Điều này làm việc cho tôi khi EF6 không thể giải thích một cách rõ ràng một lệnh đi từ cuối kịch bản tạo thủ tục được lưu trữ của tôi được chèn thông qua SqlResource. Sự kỳ diệu của EF không phải là điều tôi thích. – aaaaaa