DDD ile işlem tutarlılığının sağlanması


9

DDD ile başlıyorum ve uluslar arası tutarlılığı sağlamak için toplam köklerin kullanıldığını anlıyorum. Bir uygulama hizmetinde birden fazla toplama değiştirmemeliyiz.

Ancak aşağıdaki durumla nasıl başa çıkacağımı bilmek istiyorum.

Ürünler adlı toplu bir köküm var.

Grup adı verilen bir toplu kök de vardır.

Her ikisinin de kimliği vardır ve bağımsız olarak düzenlenebilir.

Birden Çok Ürün aynı Gruba işaret edebilir.

Bir ürünün grubunu değiştirebilecek bir uygulama hizmetim var:

ProductService.ChangeProductGroup(string productId, string groupId)

  1. Kontrol grubu var
  2. Depodan ürün al
  3. Grubunu ayarla
  4. Ürünü depoya geri yaz

Ayrıca grup silinebilir bir uygulama hizmeti var:

GroupService.DeleteGroup(string groupId) 1. groupId sağlanan groupId olarak ayarlanmış depodan ürün alın, sayımın 0 olduğundan emin olun veya iptal edin 2. Grubu grup havuzundan grubu silin 3. Değişiklikleri kaydedin

Sorum şu senaryo, ne olur:

ProductService.ChangeProductGroup'ta grubun var olduğunu (varsa) kontrol ederiz, ardından bu kontrolün hemen ardından ayrı bir kullanıcı productGroup'u siler (diğer GroupService.DeleteGroup aracılığıyla). Bu durumda, yeni silinen bir ürüne bir referans belirledik mi?

Bu farklı bir etki alanı tasarımı (gerekirse ek öğeler ekleme) kullanmalıyım ki tasarımımda bir kusur mu, yoksa işlemleri kullanmak zorunda mıyım?

Yanıtlar:


2

Aynı sorun bizde de var.

Ve ben bu sorunu çözmek için hiçbir yol se ama en kötü durumda bir istisna almak için DB veya tutarlılık kontrol DB ile.

Ticari işlem tamamlanıncaya kadar serileştirilebilir işleme eşdeğer olan kötümser kilidi, toplam kökü veya sadece onun parçalarını diğer müşteriler için de kullanabilirsiniz.

Yoğun şekilde gitme şekliniz sisteminize ve iş mantığınıza bağlıdır.
Eşzamanlılık hiç de kolay bir iş değildir.
Bir problem tespit edebilseniz bile nasıl çözeceksiniz? İşlemi iptal etmeniz veya kullanıcının değişiklikleri 'birleştirmesine' izin vermeniz yeterli mi?

Entity Framework kullanıyoruz ve EF6 varsayılan olarak read_commited_snapshot kullanmaktadır, bu nedenle depodan art arda iki okuma bize tutarsız veriler verebilir. İş süreçlerinin daha açık bir şekilde özetleneceği ve infromed karar verebileceğimiz geleceği aklımızda tutuyoruz. Ve evet hala sizin gibi model düzeyinde tutarlılığı kontrol ediyoruz. Bu en azından BL'nin DB'den ayrı olarak test edilmesine izin verir.

Ayrıca , 'uzun' ticari işlemleriniz olması durumunda depo tutarlılığını düşünmenizi öneririm . Olduğu gibi oldukça zor.


1

Bu, Etki Alanına Dayalı Tasarım'a özgü bir soru değil, kaynak yönetimi sorusudur.

Kaynaklar basitçe olmalıdır kilitli onlar gibi kazanılmış .

Bu, uygulama hizmeti önceden edinilen kaynağın ( Groupörneğinizdeki toplam) değiştirileceğini bildiğinde geçerlidir . Etki Alanına Dayalı Tasarım'da, kaynak kilitleme, depoya ait bir özelliktir.


Hayır, kilitleme bir "zorunluluk" değildir. Aslında, uzun süren işlemlerle yapmak oldukça korkunç bir şey. Her modern ORM'nin kutunun dışında desteklediği iyimser eşzamanlılığı kullanmaktan daha iyisiniz. Ve iyimser eşzamanlılık ile ilgili en iyi şey, atomik güncellemeleri destekledikleri sürece işlem dışı veritabanlarıyla da çalışmasıdır.
Aaronaught

1
Uzun süren işlemlerde kilitlemenin dezavantajlarını kabul ediyorum, ancak @ g18c tarafından açıklanan senaryo tam tersi, yani bireysel agregalar üzerinde kısa işlemler için ipucu veriyor.
rucamzu

0

Ürün kimliklerini neden Grup kuruluşunda saklamıyorsunuz? Bu şekilde, işleri kolaylaştıracak tek bir agrega ile uğraşırsınız.

Daha sonra bir tür eşzamanlılık modeli uygulamanız gerekir; örneğin, iyimser eşzamanlılık seçerseniz, Grup varlığına bir sürüm özelliği ekleyin ve sürümler güncellenirken eşleşmezse bir istisna atın.

Gruba ürün ekleme

  1. Ürünün var olup olmadığını kontrol edin
  2. Grubu depodan al (sürüm kimliği özelliği dahil)
  3. Group.Add (ProductId)
  4. Havuzu kullanarak Grubu kaydedin (yeni sürüm kimliğiyle güncelleyin ve sürümün değişmediğinden emin olmak için bir konum cümlesi ekleyin.)

Birçok ORM, sürüm kimlikleri veya zaman damgaları kullanılarak oluşturulmuş iyimser eşzamanlılığa sahiptir, ancak kendi rulolarınızı oluşturmak kolaydır. İşte Nhibernate http://ayende.com/blog/3946/nhibernate-mapping-concurrency'da nasıl yapıldığına dair iyi bir yazı .


0

İşlemler yardımcı olabilse de, özellikle senaryonuz sadece birkaç vaka ile sınırlıysa başka bir yol daha vardır.

Mutasyonları yapan sorgulara kontrolleri dahil ederek her bir kontrol ve mutasyon çiftini etkili bir şekilde atomik bir işlem haline getirebilirsiniz.

Ürün güncelleme sorgusu iç öğesi (yeni başvurulan) grubuna katılır. Bu, o grup gittiğinde hiçbir şeyi güncellememesine neden olur.

Grup silme sorgusu, kendisine işaret eden tüm ürünlere katılır ve birleştirme sonucunun (herhangi bir sütunu) boş olması gereken ek koşula sahiptir. Bu, herhangi bir ürün işaret ediyorsa hiçbir şeyi silmemesine neden olur.

Sorgular, eşleşen veya güncellenen satır sayısını döndürür. Sonuç 0 ise, bir yarış koşulunu kaybettiniz ve hiçbir şey yapmadınız. Bir istisna atabilir ve uygulama katmanı, en baştan istediği gibi istediği gibi işleyebilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.