Авторwww.itsvse.com @小渣渣 ! Вмъкнете базовите данни успешно! Тестването на функцията ConcurrencyCheck е завършено Актуализацията е успешна! Бележка 1 Актуализацията е изключителна! Бележка 2, необичайна информация! Изявлението за обновяване, вмъкване или изтриване засегна неочакван брой редове (0). Обектите може да са били модифицирани или изтрити след зареждането им. Вижте http://go.microsoft.com/fwlink/?LinkId=472540 за информация относно разбирането и справянето с оптимистични изключения за паралелност.
Тествайте разликата между Timestamp и Concurrency Check АктуализацияTab1 актуализация успешна! Име 1 UpdateTab2 актуализация е успешна! Име 1 UpdateTab2 ъпдейт е ненормален! Име 2, необичайна информация! Изявлението за обновяване, вмъкване или изтриване засегна неочакван брой редове (0). Обектите може да са били модифицирани или изтрити след зареждането им. Вижте http://go.microsoft.com/fwlink/?LinkId=472540 за информация относно разбирането и справянето с оптимистични изключения за паралелност. АктуализацияTab1 актуализация успешна! Име 2
【TimeStamp】 Функцията TimeStamp може да се приложи към класа полето, който има само едно свойство байтов масив, и тази функция задава типа tiemStamp на колоната. При конкурентни проверки Code-First автоматично използва това поле тип TimeStamp.
【ConcurrencyCheck】 Функцията Concurrency Check може да се приложи към свойствата на клас на домейн. Когато EF извършва операция за обновяване, Code-First въвежда стойността на колоната в позицията where condition и можете да използвате тази функция CurrencyCheck, за да използвате съществуващите колони за проверка на конкурентността, вместо да използвате отделна колона TimeStamp за проверка на конкурентност.
Нека започнем с създаване на нов контекстен обект, за да покажем разликата между Timestamp и Concurrency Check при обработката на паралелност!
Ето кода за контекста:
Нека разгледаме колоните на базата данни, както следва:
Ще установим, че tab1 и tab2 имат колони Id, Name и Remark, а tab2 има повече колони RowVersion от tab1.
Първо прикачете тестовия код:
【Concurrency Check Principle】
Добавихме функцията Concurrency Check към свойството Renote на Tab1,
Когато актуализираме стойността на атрибута Име на същите данни по едно и също време, няма изключение!
Генерирайте SQL оператори:
изпълнителен sp_executesql N'UPDATE [dbo]. [Таб1] SET [Име] = @0 КЪДЕТО (([Id] = @1) И ([Забележка] = @2)) ',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0=N'name1',@1=1,@2=N'Note1' изпълнителен sp_executesql N'UPDATE [dbo]. [Таб1] SET [Име] = @0 КЪДЕТО (([Id] = @1) И ([Забележка] = @2)) ',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0=N'name2',@1=1,@2=N'note1' Когато обновяваме стойността на свойството Remark на същите данни по едно и също време, правим изключение!
Генерирайте SQL оператори:
изпълнителен sp_executesql N'UPDATE [dbo]. [Таб1] SET [Забележка] = @0 КЪДЕТО (([Id] = @1) И ([Забележка] = @2)) ',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0=N'Note1',@1=1,@2=N'Note' изпълнителен sp_executesql N'UPDATE [dbo]. [Таб1] SET [Забележка] = @0 КЪДЕТО (([Id] = @1) И ([Забележка] = @2)) ',N'@0 nvarchar(max) ,@1 int,@2 nvarchar(max) ',@0=N'Note 2',@1=1,@2=N'Note' Можем да установим, че ако вземем същия парче данни с Id 1 едновременно, ще получим стойността на атрибута Remark, а при обновяване на атрибута Remark ще използваме Remark като условие за обновяване.
Първото sql изявление може да бъде успешно обновено, след което коментарът се променя на "бележка 1", а когато второто sql изявление бъде обновено, актуализацията ще се провали, защото стойността на забележката се е променила.
【Принцип на времеви печат】
Добавихме свойство RowVersion в Tab2 (можете да вземете всяко име) и добавихме функцията Timestamp!!
Когато обновяваме стойността на името на същите данни по едно и също време, първата актуализация успява, втората се проваля и се появява изключение, нека разгледаме генерирания SQL код!
изпълнителен sp_executesql N'UPDATE [dbo]. [Таб2] SET [Име] = @0 КЪДЕТО ((([Id] = @1) И ([RowVersion] = @2)) И ([Забележка] = @3)) SELECT [РедВерсия] ОТ [dbo]. [Таб2] КЪДЕТО @@ROWCOUNT > 0 И [Id] = @1',N'@0 nvarchar(max) ,@1 int,@2 binary(8),@3 nvarchar(max) ',@0=N'Name1',@1=1,@2=0x00000000000007D1,@3=N'Note' изпълнителен sp_executesql N'UPDATE [dbo]. [Таб2] SET [Име] = @0 КЪДЕТО ((([Id] = @1) И ([RowVersion] = @2)) И ([Забележка] = @3)) SELECT [РедВерсия] ОТ [dbo]. [Таб2] КЪДЕТО @@ROWCOUNT > 0 И [Id] = @1',N'@0 nvarchar(max) ,@1 int,@2 binary(8),@3 nvarchar(max) ',@0=N'name2',@1=1,@2=0x00000000000007D1,@3=N'Note' При изпълнение на второто SQL изявление, тъй като данните от условието where вече не могат да бъдат намерени, актуализацията се проваля и се появява изключение!!
След като първото sql изявление бъде успешно изпълнено, стойността на RowVersion ще се промени, както е показано на фигурата по-долу:
RowsVersion е времеви печат
Заобиколно решение за липсващи актуализации
Концепция за липсващи актуализации: Когато потребителите модифицират ред данни едновременно, първо четат данните, поставят ги на фронтенда за модификация и след това ги подават при промяна, така че крайните подадени данни да презапишат предварително подадените данни, което води до загубата на актуализацията.
Накратко, ето начини да избегнете загуба на актуализации:
Използвайте времевия печат RowsVersion.
Ако редът е несъвместим със стойността преди четене, това означава, че друга транзакция е обновила тази колона, така че тази колона не може да бъде обновена, като по този начин се предотвратява загубата на актуализации.
Накрая, прикачете изходния код:
CodeFirstDemo.rar
(4.94 KB, Брой изтегляния: 13)
|