2017-01-03 68 views
1

我有一個使用EF6更新數據的C#web。並在更新期間觸發SQL Server觸發器。觸發應該由C#EF6 code-first EntityState

SELECT 
    @Columns_Updated = ISNULL(@Columns_Updated + ',', '') + name 
FROM  
    syscolumns 
WHERE 
    id = @idTable 
    AND CONVERT(VARBINARY, REVERSE(COLUMNS_UPDATED())) & POWER(CONVERT(BIGINT, 2), colorder - 1) > 0 

我有一個問題,在下面的語句

CrmClientContact t1 = dbdb.CrmClientContact.Where(x => x.rowId == 4).FirstOrDefault(); 
t1.updatedAt = DateTime.Now; 
dbdb.Entry(t1).State = EntityState.Modified; 
dbdb.SaveChanges(); 

CrmClientBetLimit t2 = dbdb.CrmClientBetLimit.Where(x => x.rowId == 1028).FirstOrDefault(); 
t2.updatedAt = DateTime.Now; 
dbdb.Entry(t2).State = EntityState.Modified; 
dbdb.SaveChanges(); 

CrmClientCLState t3 = dbdb.CrmClientCLState.Where(x => x.rowId==1).FirstOrDefault(); 
t3.updatedAt = DateTime.Now; 
dbdb.Entry(t3).State = EntityState.Modified; 
dbdb.SaveChanges(); 

找到更新的列這是我平時做的更新在EF6框架記錄。

如圖所示,我在這3個表中更新了字段updatedAt

然而,觸發完全不同的顯示@Columns_Updated

表1:的clientId,createdAt,createdBy,姓名,ROWID在t1(它有在表11列)

表2:betLimitValueSum ,的clientId,createdAt,createdBy,currId,updatedAt,updatedBy爲T2(它在表8列)

表3 ROWID爲T3(它公頃s表中的9列)

我找不到他們返回這些列的原因。

注:這兩個表的列createdAt, createdBy, updatedAt, updatedBy

爲了解決這個問題,我試圖從代碼

dbdb.Entry(t1).State = EntityState.Modified; 
dbdb.Entry(t2).State = EntityState.Modified; 
dbdb.Entry(t3).State = EntityState.Modified; 

刪除這些報表。因此,我認爲這個問題是EntityStatedb.SaveChange()連接。

我想知道

  1. 爲什麼附EntityState會導致這些意外的更新列在數據表中出現?

  2. 當我應該附上EntityState.Modified(我認爲在更新記錄像上面的代碼時這樣做是正確的,但顯然觸發器顯示不是)?

-----------------更新----------------- 刪除EntityState.Modified後從碼。觸發仍無法收到正確@UpdatedColumns,我曾嘗試下面的代碼

t3 = dbdb.CrmClientContact.Where(x => x.rowId == 7).FirstOrDefault(); 
t3.updatedAt = DateTime.Now; 
t3.updatedBy = DateTime.Now.ToString(); 
t3.mobile = DateTime.Now.ToString(); 
t3.name = DateTime.Now.ToString(); 
dbdb.SaveChanges(); 

然而,在觸發它返回createdAt,ROWID作爲更新列。請注意,一些表格可以工作。

而且行爲對我來說是意想不到的。對於實施例

CrmClientContact t3 = dbdb.CrmClientContact.Where(x => x.rowId == 5).FirstOrDefault(); 
t3.updatedAt = DateTime.Now; 
t3.email = DateTime.Now.ToString(); 
dbdb.SaveChanges(); // correct 

t3 = dbdb.CrmClientContact.Where(x => x.rowId == 5).FirstOrDefault(); 
t3.updatedAt = DateTime.Now.AddDays(1); 
t3.email = DateTime.Now.ToString() + 1; 
dbdb.SaveChanges(); //correct 

t3 = dbdb.CrmClientContact.Where(x => x.rowId == 5).FirstOrDefault(); 
t3.updatedAt = DateTime.Now.AddDays(2); 
t3.email = DateTime.Now.ToString() + 2; 
t3.mobile = DateTime.Now.ToString() + 2; 
t3.name = DateTime.Now.ToString() + 2; 
dbdb.SaveChanges(); // correct 

t3 = dbdb.CrmClientContact.Where(x => x.rowId == 5).FirstOrDefault(); 
t3.updatedAt = DateTime.Now; 
t3.updatedBy = DateTime.Now.ToString();      
dbdb.SaveChanges(); // correct 

t3 = dbdb.CrmClientContact.Where(x => x.rowId == 5).FirstOrDefault(); 
t3.updatedAt = DateTime.Now.AddDays(1); 
t3.updatedBy = DateTime.Now.ToString()+1; 
dbdb.SaveChanges(); // correct 

t3 = dbdb.CrmClientContact.Where(x => x.rowId == 5).FirstOrDefault(); 
t3.updatedAt = DateTime.Now.AddDays(2); 
t3.updatedBy = DateTime.Now.ToString() + 2; 
dbdb.SaveChanges(); // correct 

t3 = dbdb.CrmClientContact.Where(x => x.rowId == 5).FirstOrDefault(); 
t3.updatedBy =3+ DateTime.Now.ToString(); 
t3.email =1+ DateTime.Now.ToString(); 
dbdb.SaveChanges();//null, incorrect 

t3 = dbdb.CrmClientContact.Where(x => x.rowId == 5).FirstOrDefault(); 
t3.updatedBy =2+ DateTime.Now.ToString(); 
t3.email =1+ DateTime.Now.ToString(); 
dbdb.SaveChanges();//updatedBy, incorrect (email is missing) 

t3 = dbdb.CrmClientContact.Where(x => x.rowId == 5).FirstOrDefault(); 
t3.updatedBy = 22 + DateTime.Now.ToString(); 
t3.email = 11 + DateTime.Now.ToString(); 
dbdb.SaveChanges();//null, incorrect 

t3 = dbdb.CrmClientContact.Where(x => x.rowId == 5).FirstOrDefault(); 
t3.updatedBy = 222 + DateTime.Now.ToString(); 
t3.email = 111 + DateTime.Now.ToString(); 
dbdb.SaveChanges();//null, incorrect 

t3 = dbdb.CrmClientContact.Where(x => x.rowId == 5).FirstOrDefault(); 
t3.updatedBy = 22 + DateTime.Now.ToString(); 
t3.email = 11 + DateTime.Now.ToString(); 
dbdb.SaveChanges();//null, incorrect 
CrmClientContact t4 = dbdb.CrmClientContact.Where(x => x.rowId == 5).FirstOrDefault(); 
t4.updatedBy = 2 + DateTime.Now.ToString(); 
t4.email = 1 + DateTime.Now.ToString(); 
dbdb.SaveChanges();//null, incorrect 

如上所示,I完全不明白如何可以發生上述結果集(它們是確定性的,且可重複的)

----------- ---最終更新-------------- 使用SQL事件探查器後,我發現EF6的SQL查詢只是一個與文檔匹配的正常更新語句。在管理工作室中執行相同的SQL時,可以再現相同的結果(無法在觸發器中找到UPDATED COLUMN)。

因此,我認爲SQL Server Update Trigger, Get Only modified fields只能用於以前版本的SQL Server。

至少我的數據庫(SQLSERVER 2014(120))無法將標記的答案應用於查找更新的列。

最後,我應用了另一個支持刪除和插入表並找到不同的另一個,沒有理由再失敗,除了它需要表中的一個不變的列(幸運的是我所有的表都有主鍵, )。

唯一的問題是維護每個表修改的觸發器。

謝謝。

回答

0

MSDN:修改後,當調用SaveChanges所有屬性值將被髮送到數據庫

當您更改狀態修改的所有實體的屬性將被標記。

當您從數據庫檢索實體對象時,EF會爲您跟蹤實體對象的狀態。這意味着更改任何屬性值並使用SaveChanges保存實體也將保持您的更改,並且不需要明確將實體狀態標記爲EntityState.Modified

希望這會有所幫助。

P.S.如果您有審覈要求,您可以查看EntityFramework-Plus Audit。我建議,因爲我們在工作中使用它,而且我沒有與「EntityFramework-Plus」的關係。

+0

奇怪的是,附加的EntityState並沒有更新所有的列。我認爲這是因爲SQL語句不適用於查找更新的列。但是如果我直接在management studio中執行SQL,我可以正確地獲得更新的列。這是我真正懷疑的主要問題。實際上,我只是想用EF6執行「update t1 set updatedAt = GETDATE()where rowid = 4」,這樣我就可以在觸發器中將updatedAt更新爲@UpdatedColumn。不幸的是,上述EF6更新無效(它返回奇怪的列!) – SKLTFZ

+0

@SKLTFZ在這種情況下,我會建議記錄SQL查詢。您可以查看https://msdn.microsoft.com/en-us/library/dn469464(v=vs.113).aspx#Anchor_0。或者,您可以運行SQL Server Profiler(可從SSMS獲得)來檢查針對您的數據庫正在執行的查詢。 –

+0

它的一個好主意,讓我先嚐試跟蹤查詢。謝謝 – SKLTFZ