Soru DbSet.Attach (varlık) vs DbContext.Entry (varlık) .State = EntityState.Modified


Ayrılmış bir senaryoda olduğumda ve bunu kaydetmek için bir varlık olarak eşleştirdiğim istemciden bir dto aldığımda bunu yaparım:

context.Entry(entity).State = EntityState.Modified;
context.SaveChanges();

O zaman ne için DbSet.Attach(entity)

veya EntityState.Modified öğeyi zaten eklediğinde neden .Attach yöntemini kullanmalıyım?


76
2018-06-22 19:03


Menşei


Bazı sürüm bilgilerini daha iyi ekleyin, bu daha önce sorulmuştur. Bu yeni bir soruyu hakediyorsa açık değilim. - Henk Holterman


Cevaplar:


Ne zaman yaparsın context.Entry(entity).State = EntityState.Modified;, yalnızca varlığın DbContextAyrıca, tüm varlığı kirli olarak işaretlersiniz. Bu, yaptığınız zaman anlamına gelir context.SaveChanges()EF, güncellenecek bir güncelleme deyimi oluşturacak herşey varlığın alanları.

Bu her zaman istenmez.

Diğer yandan, DbSet.Attach(entity) varlığı içeriğe ekler olmadan kirli işaretlemek. Bu eşdeğerdir context.Entry(entity).State = EntityState.Unchanged;

Bu şekilde iliştirdiğinizde, daha sonra varlığınızdaki bir özelliği güncellemeye devam etmediğiniz sürece context.SaveChanges()EF, bu varlık için bir veritabanı güncellemesi oluşturmaz.

Bir öğeye yönelik bir güncelleme yapmayı planlıyor olsanız bile, varlığın çok fazla özelliği varsa (db sütunları) ancak yalnızca birkaçını güncellemek istiyorsanız, bunu yapmanız avantajlı olabilir. DbSet.Attach(entity)ve sonra yalnızca güncellenmesi gereken birkaç özelliği güncelleyin. Bu şekilde yapmak, EF'den daha verimli bir güncelleme beyanı oluşturacaktır. EF yalnızca değiştirdiğiniz özellikleri günceller (aksine context.Entry(entity).State = EntityState.Modified; tüm özelliklerin / sütunların güncellenmesine neden olacak)

İlgili belgeler: Ekle / Ekle ve Varlık Durumları.

Kod örneği

Şu varlığa sahip olduğunuzu varsayalım:

public class Person
{
    public int Id { get; set; } // primary key
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Kodunuz şunun gibi görünüyorsa:

context.Entry(personEntity).State = EntityState.Modified;
context.SaveChanges();

Oluşturulan SQL böyle bir şeye benzeyecektir:

UPDATE person
SET FirstName = 'whatever first name is',
    LastName = 'whatever last name is'
WHERE Id = 123; -- whatever Id is.

Yukarıdaki güncelleme ifadesinin, tüm sütunları nasıl güncelleyeceğini veya değerleri gerçekten değiştirip değiştirmediğinizi fark edebilirsiniz.

Aksine, kodunuz "normal" Bunu şöyle eklerse:

context.People.Attach(personEntity); // State = Unchanged
personEntity.FirstName = "John"; // State = Modified, and only the FirstName property is dirty.
context.SaveChanges();

Sonra oluşturulan güncelleme bildirimi farklıdır:

UPDATE person
SET FirstName = 'John'
WHERE Id = 123; -- whatever Id is.

Gördüğünüz gibi güncelleme bildirimi bir tek Varlığı bağlama ekledikten sonra gerçekten değiştirilen değerleri güncelleştirir. Tablonuzun yapısına bağlı olarak, bu olumlu bir performans etkisine sahip olabilir.

Şimdi, hangi seçenek sizin için daha iyidir, yapmaya çalıştığınız şey tamamen bağlıdır.


184
2018-06-22 19:24



Detayları ile iyi cevap! - Elisabeth
EF, WHERE yan tümcesini bu şekilde oluşturmaz. Yeni (yani yeni Entity ()) ile oluşturulmuş bir varlığı ekleyip değiştirdiyseniz, iyimser kilit nedeniyle tüm orijinal alanları ayarlamanız gerekir. UPDATE sorgusunda oluşturulan WHERE yan tümcesi genellikle tüm orijinal alanları (yalnızca Id değil) içerir, dolayısıyla bunu yapmazsanız EF eşzamanlılık özel durumu atar. - bubi
@budi: Geri bildiriminiz için teşekkür ederim. Emin olmak için tekrar test ettim ve temel bir varlık için tanımladığım gibi davrandım. WHERE Yalnızca birincil anahtarı içeren ve eşzamanlılık denetimi içermeyen yan tümce. Eşzamanlılık kontrolüne sahip olmak için, bir sütunu eşzamanlı bir simge veya rowVersion olarak açıkça yapılandırmam gerekiyor. Bu durumda WHERE tüm alanları değil, yalnızca birincil anahtar ve eşzamanlı simge belirteci sütununa sahip olur. Testleriniz aksini gösteriyorsa, bunu duymak isterim. - sstan
Cadı mülkünü dinamik olarak nasıl değiştirebilirim? - Navid_pdp11
@ Navid_pdp11 DbContext.Entry(person).CurrentValues ve DbContext.Entry(person).OriginalValues. - Shimmy


Kullandığınızda DbSet.Update yönteminde, Varlık Çerçevesi, varlığınızın tüm özelliklerini işaretler. EntityState.Modified, bu yüzden onları izler. Tüm özelliklerinizi değiştirmek isterseniz, tümünü kullanmayın. DbSet.Attach. Bu yöntem tüm özelliklerinizi sağlar EntityState.Unchanged, bu yüzden güncellemek istediğiniz mülklerinizi yapmalısınız EntityState.Modified. Böylece uygulama isabet ettiğinde DbContext.SaveChangessadece değiştirilmiş özellikleri kullanacaktır.


0
2017-09-15 07:27