2010-12-14 14 views
14

Moje repozytorium działa w modelu UnitOfWork; wszystkie operacje, niezależnie od tego, czy są pobierane czy utrwalane, muszą być wykonywane w ramach obiektu tokenu IDisposableUnitOfWork, który za kulisami jest powiązany z Session, który wykonuje żądaną pracę. Tak, to jest podstawowy wzór:Dołączanie odłączonego obiektu do sesji NHibernate; najlepsze praktyki?

using (var uow = repo.BeginUnitOfWork()) 
{ 
    try 
    { 
     //DB operations here; all repo methods require passing in uow. 
     ... 
     repo.CommitUnitOfWork(uow); 
    } 
    catch(Exception) 
    { 
     repo.RollbackUnitOfWork(uow); 
     throw; 
    } 
} 

Ja również wdrożone pewne metody otoki, które pozwalają określić lambda lub pełnomocnik, który będzie realizowany w tym zakresie, łagodzi potrzebę wdrożenia wszystkie rusztowania za każdym razem.

Problem polega na tym, że przy użyciu tego modelu kod musi "wiedzieć", czego potrzebuje użytkownik, i szybko załadować go za pomocą NHUtil.Initialize() w ramach UnitOfWork. Po umieszczeniu komunikatu UOW na końcu bloku używanego sesja powiązana z dowolnym numerem PersistentBags jest zamknięta, więc nie można ich ocenić. Jakkolwiek pochopne ładowanie wszystkiego z góry nie zawsze jest wykonalne i rodzaj pokonuje cel leniwego ładowania ORM, implementuję metodę Attach().

Oto pytanie; W przypadku braku wbudowanej metody ISession.Attach() istnieją trzy metody, które widziałem, aby skojarzyć obiekt z nową sesją. Który z nich jest najlepszą praktyką, aby wykonać zadanie?

A:

if(!Session.Contains(domainObject)) 
    Session.Update(domainObject); 

B:

Session.Merge(domainObject); 

C:

Session.Lock(domainObject, LockMode.None); 

Odpowiedz

24

: Brak powyższych. Skuteczne wyłączanie leniwego ładowania przez zbyt krótki czas UOW i pokonanie celu LM-ładującego ORM. Fakt, że musisz ponownie skojarzyć odłączone obiekty w zwykły sposób, oznacza, że ​​granice jednostek pracy są błędne.

Merge, Update i zablokować wszystkie mają różne cele. Jeśli utkniesz w swojej obecnej architekturze, Lock jest prawdopodobnie tym, czego chcesz.

  • Update - kojarzy zmienił obiektowi
  • Lock - współpracowników niezmienione obiektu
  • Merge - jeśli obiekt istnieje w bieżącej sesji to jest aktualizowana ze zmianami z połączonego obiektu inaczej to Blokada taka sama jak
+0

Fair enough. Nie utknąłem w obecnej architekturze repo. Podstawowy wzór jest taki, że obiekt UnitOfWork jest tokenem typu flyweight, który implementuje IDisposable, wywołując repozytorium po usunięciu, aby sesja została oczyszczona. Obecnie funkcja Dispose() MUSI być wywołana przez kod użytkownika, inaczej DB pozostanie otwarty, więc wzorzec użycia jest najbardziej logiczny. implementacja IDisposable może być bardziej niezawodna, więc jest wywoływana w razie potrzeby, gdy obiekt jest GCed, lub mogę spojrzeć na inny wzorzec. Twoje sugestie? – KeithS

+0

W rzeczywistości anuluj część "czyniącą bardziej niezawodną"; istnieje odniesienie do UOW w repozytorium, więc dopóki nie zostanie jawnie unieważnione, nie będzie do dyspozycji repozytorium (i pozostanie w pamięci przez kontener IoC przez cały czas trwania programu). – KeithS

+0

Powinieneś przekazać swój UOW do konstruktora repozytorium. Osobiście używam ISession bezpośrednio, zamiast go owijać.Utylizacja ISIS jest ważna, ale w wielu przypadkach niepraktyczne jest zawinięcie jej w blok przy użyciu i musisz wywołać Dispose w odpowiednim czasie. –