2013-08-20 26 views
0

我制訂類似下面的類:CompositeId和IDENTITY_INSERT

public class FooMap : ClassMap<Foo> 
{ 
    public FooMap() 
    { 
    Table("Foo"); 
    LazyLoad(); 
    CompositeId().KeyProperty(x => x.ID, 
           kp => kp.ColumnName("Id") 
             .Type(typeof(long))) 
       .KeyProperty(x => x.ValidFrom); 
    } 
} 

在MSSQL側,編號爲標識列和表的PK是由IdValidFrom

這裏是我用來保存代碼:

ISession session = SessionService.GetSession();  
new SqlCommand("SET IDENTITY_INSERT Foo ON", 
       session.Connection as SqlConnection) 
       .ExecuteNonQuery(); 

try 
{ 
    // performs various versioning checks, 
    // then saves using transaction. 
    // The session is the same as above 
    GenericDataService.Save(myFoo); 
} 
finally 
{ 
    new SqlCommand("SET IDENTITY_INSERT Foo OFF", 
        session.Connection as SqlConnection) 
        .ExecuteNonQuery(); 
} 

雖然我設置Identity_InsertON,我得到下面的異常(保持ID時和設置新ValidFrom):

Cannot insert explicit value for identity column in table 'Foo' when IDENTITY_INSERT is set to OFF. 

這是執行的SQL:

INSERT INTO Foo (C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, Id, ValidFrom) 
    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 

任何人都可以解釋爲什麼我仍然得到這個異常?

+2

是錯誤數據庫錯誤或NHibernate的錯誤?只是猜測,但我認爲'Set Identity_Insert Foo on'可能不會作爲同一事務的一部分運行。嘗試使用SQL Profiler查看數據庫實際執行的內容 –

+0

感謝Nathan - 根據您的說法和我的代碼(它說「//使用事務保存」的部分)來判斷,這可能只是案件。我會在這裏檢查並回復... –

回答

0

如果問題與建議的Nathan Fisher等單獨事務有關,那麼NHibernate的ITransaction.Enlist(IDbCommand)方法應該修復它。嘗試是這樣的:

using (var trx = session.BeginTransaction()) 
{ 
    ExecuteInNHTransaction(session, "SET IDENTITY_INSERT Foo ON"); 
    session.Save(myFoo); 
    ExecuteInNHTransaction(session, "SET IDENTITY_INSERT Foo OFF"); 
    trx.Commit(); 
} 
private static void ExecuteInNHTransaction(ISession session, string commandText) 
{ 
    var command = new SqlCommand(commandText, 
     (SqlConnection) session.Connection); 
    session.Transaction.Enlist(command); 
    command.ExecuteNonQuery(); 
} 
+0

Nathan Fisher的評論給我帶來了問題,但是評論不能被標記爲答案......因爲我不在這個交易的範圍之內,所以使用命令是不行的。不管怎麼說,還是要謝謝你! –

+0

但你有權訪問NHibernate'會話'!爲什麼它不是一個選項?只需用'session.SaveOrUpdate'將您的調用替換爲'GenericDataService.Save'即可。你對這個問題的解決方案是什麼 - 你在做什麼? –

+0

GenericDataService.Save()方法包含了很多版本控制邏輯,在某些情況下,這些邏輯包括在實體持久化之前必須刪除實體,所以這不能被替換。發生在那裏的所有事情發生在交易中。 –