2016-08-18 76 views
2

我必須能夠設置我嘗試添加到我的列表「final_zones」中的實體的主鍵。我有一個控制器的構造函數如下:EF 7身份插入問題

public UtilController(CFETSContext context) 
    { 
     _context = context; 
    } 
    ......Then in a web api method......... 
     using (var transaction = _context.Database.BeginTransaction()) 
     { 
      _context.Database.ExecuteSqlCommand(@"SET IDENTITY_INSERT [CFETSWeb].[dbo].[Zone] ON");    

      _context.SaveChanges(); 
      transaction.Commit(); 
     } 


     using (var transaction = _context.Database.BeginTransaction()) 
     {    
      _context.Zones.AddRange(final_zones); 
      _context.SaveChanges(); //ERROR HERE 
      transaction.Commit(); 
     } 

不管我做什麼,我似乎無法得到IDENTITY_INSERT開啓。我得到以下錯誤:

{"Cannot insert explicit value for identity column in table 'Zone' when IDENTITY_INSERT is set to OFF."} 

我似乎無法讓它關閉。我可以在控制器中添加實體到我的數據庫中,所以我知道其他一切正在工作。我曾嘗試在沒有交易的情況下做到這一點,並得到相同的結果。

_context.Database.ExecuteSqlCommand(@"SET IDENTITY_INSERT [CFETSWeb].[dbo].[Zone] ON"); 
_context.Zones.AddRange(final_zones); 
     _context.SaveChanges(); 

任何想法?我無法接受下一步嘗試。謝謝。

+0

只是爲了確認,你是否已經將區域模型的主鍵屬性裝飾/配置爲鍵? – Developer

+0

看到這個:http://blog.robertobonini.com/2014/10/09/entity-framework-with-identity-insert/ –

+0

是的。 [Key] public int ZoneId {get;組; } –

回答

4

我用下面的解決了這個問題:

 using (var dbContextTransaction = _context.Database.BeginTransaction()) 
     { 
      try 
      { 
       _context.Database.ExecuteSqlCommand(@"SET IDENTITY_INSERT [CFETSWeb].[dbo].[Zone] ON"); 
       _context.Zones.AddRange(final_zones); 
       _context.SaveChanges();   

       dbContextTransaction.Commit(); 
      } 
      catch (Exception e) 
      { 
       dbContextTransaction.Rollback(); 
      } 
     } 

注:你必須要做到這一點每個表。 IDENTITY_INSERT每次只能爲一個表設置,因此您可以按照這種方式進行設置,或者在同一個事務中將其切換爲OFF。

此外,IDENTITY_INSERT必須在事務中,因爲它只在事務期間保持不變。

1

SET IDENTITY_INSERT語句的作用域爲一個SQL會話,這實際上等同於通過打開的連接發送的一組語句。

但是,默認情況下,EF上下文將打開並關閉每個語句的連接,並執行數據庫交互。因此,在ExecuteSqlCommand聲明之後,連接關閉,並且IDENTITY_INSERT被重置。

現在這是一個有些隱藏的功能,如果在上下文執行語句之前打開它,EF 將不會關閉連接。所以,如果你這樣做......

try 
{ 
    _context.Database.Connection.Open(); 
    _context.Database.ExecuteSqlCommand(@"SET IDENTITY_INSERT [CFETSWeb].[dbo].[Zone] ON"); 
    _context.Zones.AddRange(final_zones); 
    _context.SaveChanges(); 
} 
finally 
{ 
    _context.Database.Connection.Close(); 
} 

...你會發現IDENTITY_INSERT設置將「生存」的ExecuteSqlCommand聲明。