2017-01-03 3 views
1

Ich habe ein C# -Web mit EF6, um Daten zu aktualisieren. und ein SQL Server-Trigger wird während der Aktualisierung ausgelöst. Der Auslöser sollte durch die aktualisierte Spalte findenC# EF6 Code-zuerst 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 

ich eine Frage in folgenden Aussage habe

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(); 

Dies ist, was ich in der Regel zu aktualisieren Datensätze in dem EF6 Rahmen zu tun.

Wie gezeigt, habe ich das Feld updatedAt in diesen 3 Tabellen aktualisiert.

zeigte jedoch der Auslöser vollständig unterschiedliche @Columns_Updated

Tabelle 1: clientId, createdAt, createdBy, name, rowid für t1 (it 11 Spalten in der Tabelle besitzt)

Tabelle 2: betLimitValueSum , clientId, createdAt, createdBy, Currid, updatedAt, updatedBy für t2 (es hat 8 Spalten in der Tabelle)

Tabelle 3. rowid für T3 (it ha s 9 Spalten in der Tabelle)

Ich kann nicht den Grund finden, warum sie diese Spalten zurückgeben.

Hinweis: Die beiden Tabellen enthalten Spalten createdAt, createdBy, updatedAt, updatedBy

Um das Problem zu lösen, habe ich versucht, diese Aussagen aus dem Code

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

So entfernen Sie, ich glaube, das Problem Anbringen der EntityState vor db.SaveChange() ist.

Ich mag

  1. warum angebracht wissen, die EntityState diese unerwarteten Update Spalten in der Datentabelle auftreten verursachen würde?

  2. wenn ich die EntityState.Modified anhängen sollte (ich dachte, es ist richtig, es zu tun, wenn die Aufzeichnung wie der obige Code aktualisiert, aber offensichtlich der Trigger zeigt es nicht)?

----------------- ----------------- aktualisiert Nach entfernt EntityState.Modified aus der Code. Der Auslöser ist noch nicht richtig @UpdatedColumns erhalten, habe ich den folgenden Code versucht

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(); 

jedoch im Trigger es createdAt zurückzukehren, rowID wie die aktualisierten Spalten. Beachten Sie, dass einige Tabellen funktionieren könnten.

Und das Verhalten ist für mich unerwartet abgeschlossen.Beispiele

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 

wie oben gezeigt, kann ich nicht vollständig verstehen, wie der Satz oben Ergebnis aufgetreten sein (sie sind deterministisch und wiederholbar)

----------- --- Final Update -------------- Nach der Verwendung des SQL-Profiler habe ich festgestellt, dass die SQL-Abfrage von EF6 nur eine normale Update-Anweisung ist, die mit dem Dokument übereinstimmt. Und das gleiche Ergebnis kann reproduziert werden, wenn dasselbe SQL im Management Studio ausgeführt wird (die AKTUALISIERTE SPALTE im Trigger kann nicht gefunden werden).

Im Ergebnis denke ich SQL Server Update Trigger, Get Only modified fields kann nur für frühere Version SQL Server arbeiten.

Zumindest konnte meine Datenbank (SQLSERVER 2014 (120)) die markierte Antwort nicht anwenden, um die aktualisierten Spalten zu finden.

Schließlich habe ich einen anderen angewendet, der die gelöschte und eingefügte Tabelle schwenkt und den Unterschied findet, es gibt keinen Grund mehr zu scheitern, außer dass eine unveränderte Spalte in der Tabelle benötigt wurde (zum Glück haben alle meine Tabellen einen Primärschlüssel, der unverändert angenommen wird)).

Das einzige Problem ist Wartung der Auslöser für jede Änderung der Tabelle.

Danke.

Antwort

0

Von MSDN:

Wenn Sie den Zustand Modified alle Eigenschaften des Unternehmens markiert wird ändern, wie geändert und alle Eigenschaftswerte werden an die Datenbank gesendet werden, wenn Savechanges aufgerufen wird.

Wenn Sie ein Entitätsobjekt aus der Datenbank abrufen, verfolgt EF den Status des Entitätsobjekts für Sie. Das bedeutet, dass das Ändern eines Eigenschaftswerts und das Speichern der Entität unter Verwendung von SaveChanges auch Ihre Änderung beibehalten und Sie den Entitätsstatus nicht explizit als EntityState.Modified kennzeichnen müssen.

Hoffe, das hilft.

P.S. Wenn Sie eine Anforderung für Auditing haben, können Sie sich EntityFramework-Plus Audit ansehen. Ich schlage vor, wie wir es bei der Arbeit verwenden, und ich habe keine Verbindung mit "EntityFramework-Plus".

+0

die seltsame Sache ist, dass Anfügen von EntityState nicht alle Spalten zu aktualisieren. Ich dachte, es war wegen der SQL-Anweisung nicht funktioniert, um die aktualisierte Spalte zu finden. Aber ich kann die aktualisierten Spalten korrekt abrufen, wenn ich SQL direkt in Management Studio ausführe. Hier ist die Hauptfrage, die ich wirklich bezweifle. Eigentlich möchte ich nur EF6 verwenden, um "update t1 set updatedAt = GETDATE() wo rowid = 4" auszuführen, so dass ich im Trigger als @UpdatedColumn aktualisiert werden kann. Leider hat das obige EF6-Update nicht funktioniert (es gibt merkwürdige Spalten zurück!) – SKLTFZ

+0

@SKLTFZ In diesem Fall würde ich vorschlagen, die SQL-Abfragen zu protokollieren. Sie können https://msdn.microsoft.com/en-us/library/dn469464(v=vs.113).aspx#Anchor_0 überprüfen. Alternativ können Sie SQL Server Profiler (verfügbar von SSMS) ausführen, um zu überprüfen, welche Abfragen für Ihre Datenbank ausgeführt werden. –

+0

ist eine gute Idee, lassen Sie mich versuchen, die Abfrage zuerst zu verfolgen. Vielen Dank – SKLTFZ