Autorwww.itsvse.com @小渣渣 ! Introdu cu succes datele de bază! Testarea funcției ConcurrencyCheck este finalizată Actualizare reușită! Notă 1 Actualizarea este excepțională! Notă 2, informații anormale! Instrucțiunea de actualizare, inserare sau ștergere a stocării a afectat un număr neașteptat de rânduri (0). Entitățile pot fi modificate sau șterse de la încărcarea entităților. Consultați http://go.microsoft.com/fwlink/?LinkId=472540 pentru informații despre înțelegerea și gestionarea excepțiilor optimiste de concurență.
Testează diferența dintre Timestamp și ConcurrencyCheck Actualizare Tab1 reușită! Nume 1 Actualizarea Tab2 a fost reușită! Nume 1 ActualizareActualizarea Tab2 este anormală! Numește 2, informații anormale! Instrucțiunea de actualizare, inserare sau ștergere a stocării a afectat un număr neașteptat de rânduri (0). Entitățile pot fi modificate sau șterse de la încărcarea entităților. Consultați http://go.microsoft.com/fwlink/?LinkId=472540 pentru informații despre înțelegerea și gestionarea excepțiilor optimiste de concurență. Actualizare Tab1 reușită! Nume 2
【TimeStamp】 Funcția TimeStamp poate fi aplicată clasei câmpului, care are o proprietate de tablou de un singur octet, iar această caracteristică setează tipul tiemStamp pe coloană. În verificările concurente, Code-First folosește automat acest câmp de tip TimeStamp.
【Concurrency Check】 Funcția ConcurrencyCheck poate fi aplicată proprietăților unei clase de domeniu. Când EF efectuează o operație de actualizare, Code-First introduce valoarea coloanei în instrucțiunea condiției where, iar poți folosi această funcție CurrencyCheck pentru a folosi coloanele existente pentru verificarea concurenței, în loc să folosești o coloană TimeStamp separată pentru verificarea concurenței.
Să începem prin a crea un nou obiect de context pentru a demonstra diferența dintre Timestamp și ConcurrencyCheck în procesarea concurenței!
Iată codul pentru context:
Să aruncăm o privire la coloanele bazei de date, după cum urmează:
Vom descoperi că tab1 și tab2 au coloane Id, Nume și Remark, iar tab2 are mai multe coloane RowVersion decât tab1.
Atașează mai întâi codul de test:
【Principiul Verificării Concurenței】
Am adăugat funcția ConcurrencyCheck la proprietatea Remark din Tab1,
Când actualizăm valoarea atributului Name a acelorași date în același timp, nu se face nicio excepție!
Generează instrucțiuni SQL:
executiv sp_executesql N'UPDATE [dbo]. [Tab1] SET [Nume] = @0 UNDE (([Id] = @1) ȘI ([Remarcă] = @2)) ',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0=N'name1',@1=1,@2=N'Note1' executiv sp_executesql N'UPDATE [dbo]. [Tab1] SET [Nume] = @0 UNDE (([Id] = @1) ȘI ([Remarcă] = @2)) ',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0=N'name2',@1=1,@2=N'note1' Când actualizăm valoarea proprietății Remark a acelorași date în același timp, aruncăm o excepție!
Generează instrucțiuni SQL:
executiv sp_executesql N'UPDATE [dbo]. [Tab1] SET [Remarcă] = @0 UNDE (([Id] = @1) ȘI ([Remarcă] = @2)) ',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0=N'Note1',@1=1,@2=N'Note' executiv sp_executesql N'UPDATE [dbo]. [Tab1] SET [Remarcă] = @0 UNDE (([Id] = @1) ȘI ([Remarcă] = @2)) ',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0=N'Note 2',@1=1,@2=N'Note' Putem constata că dacă luăm aceeași bucată de date cu Id 1 în același timp, vom obține valoarea atributului Remark, iar la actualizarea atributului Remark, vom folosi Remark ca condiție de actualizare.
Prima instrucțiune sql poate fi actualizată cu succes, iar apoi remarca este schimbată în "note 1", iar când a doua instrucțiune sql este actualizată, actualizarea va eșua deoarece valoarea remarcii s-a schimbat.
【Principiul Timestamp-ului】
Am adăugat o proprietate RowVersion în Tab2 (poți lua orice nume) și am adăugat funcția Timestamp!
Când actualizăm valoarea Nume a acelorași date în același timp, prima actualizare reușește, a doua eșuează și se aruncă o excepție, hai să aruncăm o privire la codul SQL generat!
executiv sp_executesql N'UPDATE [dbo]. [Tab2] SET [Nume] = @0 UNDE ((([Id] = @1) ȘI ([RowVersion] = @2)) ȘI ([Remarcă] = @3)) SELECT [RowVersion] DE la [dbo]. [Tab2] UNDE @@ROWCOUNT > 0 ȘI [Id] = @1',N'@0 nvarchar(max) ,@1 int,@2 binary(8),@3 nvarchar(max) ',@0=N'Name1',@1=1,@2=0x00000000000007D1,@3=N'Note' executiv sp_executesql N'UPDATE [dbo]. [Tab2] SET [Nume] = @0 UNDE ((([Id] = @1) ȘI ([RowVersion] = @2)) ȘI ([Remarcă] = @3)) SELECT [RowVersion] DE la [dbo]. [Tab2] UNDE @@ROWCOUNT > 0 ȘI [Id] = @1',N'@0 nvarchar(max) ,@1 int,@2 binary(8),@3 nvarchar(max) ',@0=N'name2',@1=1,@2=0x00000000000007D1,@3=N'Note' Când rulezi a doua instrucțiune SQL, pentru că datele condiției where nu mai pot fi găsite, actualizarea eșuează și se aruncă o excepție!!
După ce prima instrucțiune sql este executată cu succes, valoarea RowVersion se va schimba, așa cum se arată în figura de mai jos:
RowsVersion este timestamp
Soluție pentru actualizările lipsă
Conceptul de actualizări lipsă: Când utilizatorii modifică o linie de date în același timp, mai întâi citesc datele, le pun în front-end pentru modificări și apoi trimit datele când sunt modificate, astfel încât datele finale trimise să suprascrie cele trimise anterior, ceea ce duce la pierderea actualizării.
Pe scurt, iată modalități de a preveni pierderea actualizărilor:
Folosește timestamp-ul RowsVersion.
Dacă un rând este inconsistent cu valoarea de dinaintea citirii, înseamnă că o altă tranzacție a actualizat această coloană, astfel încât această coloană nu poate fi actualizată, prevenind astfel pierderea actualizărilor.
În final, atașează codul sursă:
CodeFirstDemo.rar
(4.94 KB, Numărul de descărcări: 13)
|