2013-03-21 71 views
2

我有一個視圖ObjectDisplay,它由兩個相關的表格組成:ObjectStateState代表Object的狀態,並且該視圖從最近的State中爲每個Object提取一些細節。視圖是否立即反映其基礎表中的數據更改?

在顯示此信息的頁面上,用戶可以輸入一些註釋,它會創建一個新的State。在創建新的State後,我立即從ObjectDisplay中取出Object,然後將其發回並放入局部視圖中,並替換頁面上的網格中的Object

// Add new State. 
db.States.Add(new State() 
{ 
    ObjectId = objectId, 
    Comments = comments, 
    UserName = username 
}); 

// Save the changes (executes all of the above). 
db.SaveChanges(); 

// Return the new Object information. 
return db.Objects.Single(c => c.ObjectId == objectId); 

根據我的分貝跟蹤,該Single呼叫發生SaveChanges呼叫後約70毫秒,它發生在同一個SPID。

現在是問題:數據庫默認RecordDate的值在StateGETUTCDATE() - 我自己沒有提供日期。我看到的是Object返回的舊StateStateRecordDate和舊的State的新State信息的Comments我看到返回的Object有舊的State的信息。當我刷新頁面時,所有正確的信息都在那裏,但是在數據庫/ EF的初始調用中返回了錯誤的信息。

那麼..什麼可能是錯的?該視圖能否更新得足夠快? EF可能會發生什麼?我真的不知道從哪裏開始尋找。

+0

什麼隔離級別的查詢與運行?是否在不同的會話上調用視圖來更改數據? – Oded 2013-03-21 21:01:58

+0

@Oded:從跟蹤中,'Audit Login'行有'set transaction isolation level read committed'。兩者都在同一個SPID中完成。 – zimdanen 2013-03-21 21:03:56

回答

1

如果您以前在同一個DbContext中加載了相同的Object實體,EF將返回具有陳舊值的緩存實例,並忽略從SQL返回的值。

最簡單的辦法是在返回前重新加載實體:

var result = db.Objects.Single(c => c.ObjectId == objectId); 
db.Entry(result).Reload(); 
return result; 
+1

這也是我的第一個想法,但OP看到查詢在profiler中被執行。如果使用緩存值,則查詢不應該被執行。 – 2013-03-22 19:28:28

+0

'Reload'可以工作,而且我在同一個'DbContext'中加載了'Object'。我不知道爲什麼它進入數據庫,然後忽略結果並使用緩存值 - 因爲這確實是發生了什麼(即使我切換到「First」而不是「Single」)。看起來這裏最好的做法是'重新加載'我早先在'DbContext'中提取的'Object'。感謝你! – zimdanen 2013-03-22 19:58:14

+0

@SebastianMeine:不幸的是,查詢仍然會被執行,但是EF會把結果扔掉。 – 2013-03-22 20:01:21

0

這確實很奇怪。在SQL Server視圖中,默認情況下不會持久化,因此會立即顯示底層數據的更改。您可以在視圖上創建聚集索引並有效地保留查詢,但在這種情況下,數據會同步更新,因此您應該立即看到更改。

如果您使用快照隔離級別,您的更改可能不會立即對其他SPID可見,但由於您位於同一SPID並且不使用快照隔離,因此也不可能是罪魁禍首。

此時唯一剩下的就是應用程序層。你真的在調用堆棧中使用更高的Single調用結果還是會在某處丟失?我假設頁面刷新使用不同的代碼路徑,這將解釋爲什麼它在那裏工作。

+0

我正在使用結果更新Web應用程序發出呼叫的數據網格中的那一行。刷新確實使用不同的代碼路徑(通過不同的服務操作加載整個網格)。 – zimdanen 2013-03-22 13:45:10

相關問題