2012-06-30 12 views
11

Buduję aplikację z modelem domeny przy użyciu koncepcji CQRS i zdarzeń domen (ale bez gromadzenia zdarzeń, po prostu stary SQL). Nie było problemu z wydarzeniami typu SomethingChanged. Potem utknąłem w implementacji zdarzeń SomethingCreated.Nowy identyfikator jednostki w zdarzeniu domeny

Po utworzeniu elementu, który jest odwzorowany na tabelę z kluczem podstawowym tożsamości, nie znam identyfikatora, dopóki obiekt nie zostanie utrwalony. Podmiot jest wytrwałością nieświadomą, więc podczas publikowania zdarzenia z wnętrza jednostki, Id jest po prostu nieznany - jest magicznie ustawiony po wywołaniu context.SaveChanges(). Więc jak/gdzie/kiedy mogę umieścić identyfikator w danych zdarzenia?

Myślałam o:

  • włącznie z odniesieniem do jednostki w imprezie. To działałoby wewnątrz domeny, ale niekoniecznie w rozproszonym środowisku z wieloma autonomicznymi systemami komunikującymi się przez zdarzenia/komunikaty.
  • Zastępowanie SaveChanges() w celu uaktualnienia wydarzeń zapisanych do publikacji. Ale wydarzenia mają być niezmienne, więc wydaje się to bardzo brudne.
  • Pozbycie się pól tożsamości i użycie identyfikatorów GUID wygenerowanych w konstruktorze jednostki. To może być najłatwiejsze, ale może wpłynąć na wydajność i utrudnić inne rzeczy, takie jak debugowanie lub kwerendy (where id = 'B85E62C3-DC56-40C0-852A-49F759AC68FB', no MIN, MAX itp.). To właśnie widzę w wielu przykładowych aplikacjach.
  • Podejście hybrydowe - pozostaw tożsamość i używaj jej głównie dla kluczy obcych i szybszych połączeń, ale użyj identyfikatora GUID jako unikalnego identyfikatora, za pomocą którego pobierasz elementy z repozytorium w aplikacji.
+3

Nie dołączaj odniesienia do encji w wydarzeniu. Dobrze jest umieścić identyfikator po zapisaniu. Należy je uznać za niezmienne po opublikowaniu. Jednak może to być kłopotliwe, jeśli zamierzasz zezwolić na ponowne próby w kontekście tworzenia zdarzenia.Wartość przypisywania identyfikatorów z zewnątrz jest tak duża, że ​​uważam, że powinna to być domyślna strategia. Więc zarówno przy użyciu identyfikatorów GUID, jak i podejścia hybrydowego może działać. Innym podejściem może być mechanizm HILO lub coś w rodzaju płatka śniegu. –

+0

Czy mógłbyś rozwinąć HILO i płatek śniegu? – Pein

+0

http://nhforge.org/blogs/nhibernate/archive/2009/03/20/nhibernate-poid-generators-revealed.aspx i http://engineering.twitter.com/2010/06/announcing-snowflake.html –

Odpowiedz

9

Osobiście lubię identyfikatory GUID dla unikalnych identyfikatorów, zwłaszcza w środowiskach wielodostępnych, rozproszonych, gdzie numeryczne problemy powodują problemy. W związku z tym nigdy nie korzystam z kolumn/właściwości generowanych przez bazę danych i ten problem znika.

Short, że skoro jesteś po CQRS, niewątpliwie mają CreateSomethingCommand i odpowiadający CreateSomethingCommandHandler że rzeczywiście wykonuje czynności wymagane do utworzenia nowej instancji i utrzymywać nowy obiekt przy użyciu repozytorium (poprzez context.SaveChanges). Podniosę tutaj obiekt SomethingCreated, a nie obiekt domeny.

Po pierwsze, rozwiązuje to twój problem, ponieważ program obsługi komend może czekać na zakończenie operacji bazy danych, wyciągnąć wartość tożsamości, zaktualizować obiekt, a następnie przekazać tożsamość w zdarzeniu. Ale, co ważniejsze, odnosi się również do trudnego pytania, kiedy dokładnie obiekt jest "tworzony"?

Podnoszenie zdarzenia domeny w konstruktorze to zła praktyka, ponieważ konstruktorzy powinni być szczupli i po prostu wykonywać inicjalizację. Ponadto w modelu obiekt nie jest tak naprawdę tworzony, dopóki nie ma przypisanego identyfikatora. Oznacza to, że po wykonaniu konstruktora wymagane są dodatkowe kroki inicjowania. Jeśli masz więcej niż jeden krok, wymuszasz kolejność wykonywania (inny anty-wzór) lub sprawisz, że każda z nich rozpozna, kiedy wszystkie są gotowe (ooh, śmierdząca)? Mam nadzieję, że widać, jak szybko może wymknąć się spod kontroli.

Tak więc, moim zaleceniem jest podniesienie zdarzenia z obsługi komend. (UWAGA: Nawet jeśli przełączasz się na identyfikatory GUID, postępowałbym zgodnie z tym podejściem, ponieważ nigdy nie powinieneś podnosić zdarzeń od konstruktorów.)

+5

"Tak więc, moim zaleceniem jest podniesienie zdarzenia z obsługi komend" => Zdarzenia powinny brać udział w modelu domeny. Zamiast słabego konstruktora, aby zwiększyć znaczenie, utworzyłbym statyczną fabrykę: "create" podnoszącą wydarzenie w przypadku sukcesu. – Mik378

+0

"Po pierwsze, rozwiązuje to twój problem, ponieważ program obsługi komend może czekać na zakończenie operacji bazy danych, wyciągnąć wartość tożsamości" - co zrobić, jeśli timeout pojawi się gdzieś: obiekt zostanie utworzony, ale program obsługi wywoła wyjątek? Dla uproszczenia chciałbym zaimplementować program obsługi komend jako UoW. W takim przypadku musisz użyć Guid jako identyfikatora jednostki zamiast identyfikatora jednostki jako pola bazy danych tożsamości. –

Powiązane problemy