Eşzamanlılık Çakışmalarını İşleme
Not
Bu sayfa eşzamanlılık çalışma EF Core ve uygulamanıza eşzamanlılık çakışmalarını işlemeyi belgelemektedir. Modelinize eşzamanlılık belirteçlerini yapılandırma hakkında ayrıntılı bilgi için bkz. Eşzamanlılık Belirteçleri.
İpucu
Bu makalenin örneğini daha sonra GitHub.
Veritabanı eşzamanlılığı, birden çok işlem veya kullanıcının bir veritabanındaki aynı verilere aynı anda erişmesi veya değiştirmesi durumlarını ifade eder. Eşzamanlılık denetimi, eşzamanlı değişikliklerin varlığında veri tutarlılığını sağlamak için kullanılan belirli mekanizmaları ifade eder.
EF Core, birden çok işlem veya kullanıcının eşitleme veya kilitleme ek yükü olmadan bağımsız olarak değişiklik yapmalarına izin ver anlamına gelen iyimser eşzamanlılık denetimi uygulayan bir uygulamadır. İdeal durumda bu değişiklikler birbirini engellemez ve bu nedenle başarılı olabilir. En kötü durum senaryosunda, iki veya daha fazla işlem çakışan değişiklikler yapmaya çalışacak ve bunlardan yalnızca biri başarılı olacaktır.
Eşzamanlılık denetimi EF Core
Eşzamanlılık belirteçleri olarak yapılandırılan özellikler iyimser eşzamanlılık denetimi uygulamak için kullanılır: sırasında bir güncelleştirme veya silme işlemi her gerçekleştirıldığında, veritabanındaki eşzamanlılık belirtecin değeri, EF Core tarafından okunan özgün SaveChanges değerle karşılaştırıldığında.
- Değerler eş değerlerle eş değere sahipse işlem tamamlanır.
- Değerler eşleşmezse, EF Core bir işlem gerçekleştirerek geçerli işlemi durduran başka bir kullanıcı olduğunu varsayalım.
Başka bir kullanıcının geçerli işlemle çakışan bir işlem gerçekleştirdiği durum eşzamanlılık çakışması olarak bilinir.
Veritabanı sağlayıcıları eşzamanlılık belirteci değerlerinin karşılaştırmasını uygulamakla sorumludur.
İlişkisel veritabanlarında EF Core veya deyimlerinin yan tümcesinde eşzamanlılık belirtecine WHERE ilişkin bir UPDATE denetim DELETE içerir. Deyimleri yürüttkten sonra EF Core, etkilenen satır sayısını okur.
Herhangi bir satır etkilenmezse eşzamanlılık çakışması algılanır ve EF Core DbUpdateConcurrencyException olur.
Örneğin, üzerinde bir LastNamePerson eşzamanlılık belirteci olacak şekilde yapılandırmak istiyor olabiliriz. Ardından Person'daki herhangi bir güncelleştirme işlemi, yan tümcesine eşzamanlılık denetimi WHERE içerir:
UPDATE [Person] SET [FirstName] = @p1
WHERE [PersonId] = @p0 AND [LastName] = @p2;
Eşzamanlılık çakışmalarını çözme
Önceki örnekten devam etmek gerekirse, bir kullanıcı bir üzerinde bazı değişiklikleri kaydetmeye çalışırsa, ancak başka bir kullanıcı zaten değiştirirse, bir PersonLastName özel durum oluşturur.
Bu noktada, uygulama yalnızca çakışan değişiklikler nedeniyle güncelleştirmenin başarılı olmadığını kullanıcıya bildirebilir ve devam eder. Ancak kullanıcıdan bu kaydın hala aynı gerçek kişiyi temsil ettiğini ve işlemi yeniden denemesi istenebilir.
Bu işlem, eşzamanlılık çakışması çözümlemeye bir örnektir.
Eşzamanlılık çakışmalarını çözümlemek için bekleyen değişikliklerin veritabanındaki değerlerle geçerli DbContext olan birleştirilmesi gerekir. Hangi değerlerin birleştirilecekleri uygulamaya göre değişir ve kullanıcı girişi tarafından yönlendirebilir.
Eşzamanlılık çakışmalarını çözmeye yardımcı olmak için üç değer kümesi vardır:
- Geçerli değerler, uygulamanın veritabanına yazmaya çalıştığınız değerlerdir.
- Özgün değerler, herhangi bir düzenleme öncesinde veritabanından alınan değerlerdir.
- Veritabanı değerleri şu anda veritabanında depolanan değerlerdir.
Eşzamanlılık çakışmalarını işlemeye genel yaklaşım şu şekildedir:
- sırasında
DbUpdateConcurrencyExceptionSaveChangesyakala. - Etkilenen
DbUpdateConcurrencyException.Entriesvarlıklar için yeni bir değişiklik kümesi hazırlamak üzere kullanın. - Veritabanındaki geçerli değerleri yansıtacak şekilde eşzamanlılık belirtecine özgün değerleri yenileyin.
- Çakışma oluşmadan işlemi yeniden deneyin.
Aşağıdaki örnekte ve Person.FirstNamePerson.LastName eşzamanlılık belirteçleri olarak ayarlanmıştır. Kaydedecek // TODO: değeri seçmek için uygulamaya özgü mantığı dahil etmek istediğiniz konumda bir açıklama vardır.
using var context = new PersonContext();
// Fetch a person from database and change phone number
var person = context.People.Single(p => p.PersonId == 1);
person.PhoneNumber = "555-555-5555";
// Change the person's name in the database to simulate a concurrency conflict
context.Database.ExecuteSqlRaw(
"UPDATE dbo.People SET FirstName = 'Jane' WHERE PersonId = 1");
var saved = false;
while (!saved)
{
try
{
// Attempt to save changes to the database
context.SaveChanges();
saved = true;
}
catch (DbUpdateConcurrencyException ex)
{
foreach (var entry in ex.Entries)
{
if (entry.Entity is Person)
{
var proposedValues = entry.CurrentValues;
var databaseValues = entry.GetDatabaseValues();
foreach (var property in proposedValues.Properties)
{
var proposedValue = proposedValues[property];
var databaseValue = databaseValues[property];
// TODO: decide which value should be written to database
// proposedValues[property] = <value to be saved>;
}
// Refresh original values to bypass next concurrency check
entry.OriginalValues.SetValues(databaseValues);
}
else
{
throw new NotSupportedException(
"Don't know how to handle concurrency conflicts for "
+ entry.Metadata.Name);
}
}
}
}
Ek kaynaklar
Çakışma algılamalı bir EF Core örneği için bkz. ASP.NET Core çakışma algılama.