0

在我們的單元測試中,我們使用普通的ADO.NET(DataTable,DataAdapter)來準備數據庫響應。檢查結果,而測試的組件本身在NHibernate 2.1下運行。 .NET版本是3.5,SqlServer版本是2005.DataTable標識列未在DataAdapter.Update/Refresh之後設置,使用「 - 」代替「-trigger」(SqlServer 2005)

數據庫表具有標識列作爲主鍵。有些表適用於插入/更新觸發器(這是由於向後兼容性,我無法改變)。觸發器一般工作是這樣的:

create trigger dbo.emp_insert 
    on dbo.emp 
    instead of insert 
as 
begin 
    set nocount on 
    insert into emp ... 
    select @@identity 
end 

由ADO.NET DataAdapter的發行(上即時由薄ADO.NET包裝產生)insert語句嘗試檢索標識值回的DataRow:

exec sp_executesql N' 
insert into emp (...) values (...); 
select id, ... from emp where id = @@identity 
' 

但DataRow中的id-列仍然是0。當我暫時移除了扳機,它工作正常 - 然後在ID列保存數據庫設置標識值。

NHibernate的,另一方面採用這種INSERT語句:

exec sp_executesql N' 
insert into emp (...) values (...); 
select scope_identity() 
' 

這工作,NHibernate的POCO有沖洗之後正確地設置其ID屬性。這對我來說似乎有點反直覺,因爲我期望觸發器在不同的範圍內運行,因此@@身份應該比scope_identity()更適合。

所以我認爲沒有問題,我將在ADO.NET下應用scope_identity()而不是@@ identity。但是這沒有效果,DataRow值仍然沒有相應更新。

現在最好的部分是:當我從SqlServer分析器中將這兩個語句複製並粘貼到Management Studio查詢(包括「exec sp_executesql」)中,並在那裏運行它們時,結果似乎相反!那裏的ADO.NET版本工作,和NHibernate版本不(選擇scope_identity()返回null)。我試了幾次來驗證,但無濟於事。那麼,實際上這就是我所期望的 - @@身份確定,而scope_identity()失敗。

當然,在Management Studio中調用它只是顯示來自數據庫的結果集,無論在NHibernate和ADO.NET中發生的是另一個主題。另外,T-SQL SET定義的幾個會話屬性在兩種情況下是不同的(Management Studio查詢與運行時應用程序)

這對我來說是一個真正的難題。我會很高興有關這方面的任何見解。謝謝!

回答

1

找到它。身份值實際上被傳輸到DataTable中,而不是在我預期的列中。 ADO.NET不是使用現有的「id」列,而是創建了一個新的「Column1」列。

原因是這條線在觸發INSTEAD-OF結束:

select @@identity 

不幸的是,NHibernate的似乎需要在觸發器代替,結束 「選擇@@身份」(這是在提到一個Hibernate論壇發帖,我現在再次驗證 - 這確實是必要的)。但我可以從這裏繼續(適應NHibernate的方言是一種可能性)...