2010-06-25 9 views
6

Entity Framework 4 - STE - prosty DB z pojedynczych blogów tablica zawierająca kolumnę BlogID PK ...Czy Entity Framework ObjectContext poprawnie implementuje wzór Unit of Work?

var samplesDbEntities = new SamplesDBEntities(); 
var blogId = Guid.NewGuid(); 
samplesDbEntities.Blogs.AddObject(new Blog() { BlogID = blogId }); 
var objectSetResult = samplesDbEntities.Blogs 
             .Where(p => p.BlogID == blogId) 
             .SingleOrDefault(); 

(wynik wykonania kodu => objectSetResult == null po ostatnim wierszu)

AFAIK, ObjectContext jest implementacją wzoru UoW iw takim przypadku myślę, że powinienem otrzymać wynik z powrotem z ObjectSet (Repository) po prostu "oznaczony jako przejściowy" Czy ktoś może mi wyjaśnić, co robię źle i dlaczego objectSetResult ma tutaj zerową wartość ?

(Tak, jestem świadomy ObjectStateManager, ale dla mnie to jest bardziej patch do wspomnianego górnego problemu architektonicznego)

Odpowiedz

1

Wzór naruszony w tym przykładzie nie jest wzorem jednostki pracy, ale mapowaniem tożsamości.

Zmiany w jednostkach pracy wprowadzone w obiektach według kodu, zamiast zająć się nimi ręcznie.

Wzorzec odwzorowania tożsamości tworzy kontekst obiektu w celu utworzenia pojedynczego obiektu dla pojedynczej wartości klucza podstawowego.

To dziwne dla mnie, ale Entity Framework (jak również LINQ 2 SQL) nie odwzorowuje tożsamości obiektu w każdej sytuacji, a sytuacja opisana powyżej jest jednym z takich przypadków.

4

Trzeba zadzwonić

samplesDbEntities.SaveChanges(); 

przed requerying dla obiektu.

var samplesDbEntities = new SamplesDBEntities(); 
var blogId = Guid.NewGuid(); 
samplesDbEntities.Blogs.AddObject(new Blog() { BlogID = blogId }); 

samplesDbEntities.SaveChanges(); 

var objectSetResult = samplesDbEntities.Blogs 
            .Where(p => p.BlogID == blogId) 
            .SingleOrDefault(); 

Aktualizacja

Powodem dlaczego nie otrzymujesz dodatkową użytkownika z powrotem w objectSetResult jest, że wywołanie metody SingleOrDefault od An IQueryable wyniki obiektu w zapytaniu do bazy danych (rzeczywisty ciąg kwerendy SQL jest generowany przypisywanie do warunku "where" itd.), a ponieważ obiekt nie jest (jeszcze) w bazie danych, nie jest zwracany. Nowy obiekt jest jednak dołączony do kontekstu, a jego EntityState jest ustawione na "Dodano". Według MSDN obiekty w stanie Added nie mają oryginalnych wartości w ObjectStateEntry. Stan obiektów wewnątrz kontekstu obiektu jest zarządzany przez ObjectStateManager. Więc jeśli chcesz sprawdzić, czy obiekt jest naprawdę zostały dołączone, można pobrać ją dzwoniąc GetObjectStateEntry:

var samplesDbEntities = new SamplesDBEntities(); 
Blog blog = new Blog() { BlogID = Guid.NewGuid() }; 
samplesDbEntities.Blogs.AddObject("Blogs", blog); 

Blog addedBlog = (Blog)context.ObjectStateManager.GetObjectStateEntry(blog).Entity; 

Należy również pamiętać, że EntityState z pobranego obiektu jest „dodane”.

Podsumowując - w odniesieniu do wstępnego pytania, czy jest to poprawna implementacja UnitOfWork, nie widzę powodu, dlaczego nie. Rzeczywiście utrzymuje listę obiektów i śledzi zmiany, itp., Itp. Jednak napotkany problem jest związany z faktem, że pobierasz dane od dostawcy bazowego, a raczej z listy obiektów aktualnie przyłączonych do kontekst.

+0

-1 cos to nie odpowiada na dokładne pytanie "Czy Entity Framework ObjectContext jest prawidłową implementacją wzorca Unit of Work?" – Restuta

+0

Wystarczająco fair. Zobacz zaktualizowaną odpowiedź. – Yakimych

+2

Moim przypadkiem użycia jest to, że jednostka jest dodawana i pobierana przed pojawieniem się trwałości - jaki jest sens UoW, jeśli muszę utrzymywać każdą jednostkę osobno, a nie wsadowo? Co do kodu aktualizacji, nie sądzisz, że fakt, że muszę wiedzieć, że potrzebuję używać ObjectStateManager jest zły (przeciekająca infrastruktura)? Nie w przypadku mojej trywialnej próbki, ale to "get" może wystąpić w zupełnie innym miejscu, gdzie nie wiedziałbym, czy coś jest dodane. Dlaczego nie zostanie to uwięzione wewnątrz samego obiektu OBjectSet (jak powinna robić UoW) i po prostu rozpoznane w czasie trwania? –

0

Dziękuję za wyjaśnienie Twojego punktu. Dodaję to jako kolejną odpowiedź, ponieważ w tej sprawie jest sporo do powiedzenia.

AFAIK, nie ma ścisłej uniwersalnej definicji UU, więc temat jest oczywiście przedmiotem dyskusji. Moje punkty są następujące:

  1. Dodajesz obiekt do kontekstu, ale próbujesz pobrać go z bazy danych. Podsumowując, że ObjectContext nie jest prawidłową implementacją UU, nie jest logiczne.

  2. Jeśli dodajesz elementy do kontekstu, aby później je pobrać z jakiegoś powodu przed utrwaleniem zmian w db, nie używasz EF, ponieważ ma być używany.Generalnie nie powinno się używać ObjectStateManager to zrobić, ale możesz:

    Blog addedBlog = context. 
         ObjectStateManager. 
         GetObjectStateEntries(EntityState.Added). 
         Where(ent => (ent.Entity is Blog) && ((Blog)ent.Entity).BlogID == blogID). 
         Select(ent => ent.Entity as Blog). 
         SingleOrDefault(); 
    
  3. Jednostka pracy jest obiektem kontekst, który utrzymuje listę podmiotów gospodarczych, śledzi zmiany w ich stanie podczas jednej transakcji. Czy to robi obiekt ObjectContext EF? Tak. Czy zapewnia rozsądną składnię do pobrania obiektu, który jest w stanie "Dodano"? Nie, ale i tak nie jest to konieczne do "prawidłowego" wdrożenia UU. Nie zapominaj - EF to ORM, a celem jest śledzenie zmian w Twojej db w kodzie, a nie zmian między różnymi częściami twojego kodu (to jest twoja logika biznesowa).

I w sprawie: „co to jest punkt UOW jeśli mam utrzymywać się każdy podmiot, na własną rękę, a nie w partii” - chodzi o to, że można dodać kilka obiektów do kontekstu, a następnie utrzymuj je wszystkie za jednym razem, wywołując SaveChanges. Jak już wspomniałem, kontekst nie jest przeznaczony do "przenoszenia" obiektów biznesowych. Możesz jednak pobrać je z ObjectStateManager bez ciągłych zmian w DB, jeśli chcesz.

+0

Powiedziałeś "chodzi o to, że możesz dodać kilka obiektów do kontekstu, a następnie utrzymywać je wszystkie za jednym razem, wywołując SaveChanges" Zgadzam się z tym 100% (to jest to, co powiedziałem). Opisany sposób działania EF4 mogę dodać 2x Post z tym samym identyfikatorem z różnych części mojego kodu - wszystko w porządku dopóki trwa - kiedy wystąpi naruszenie PK. Nie potrzebuję więcej wyjaśnień jak działa EF4 * - Wiem o tym i myślę (architektonicznie) jest wadliwy. Wygląda na to, że pytanie typu SO nie jest dobrym medium do prowadzenia tej dyskusji, więc napisałbym tam post na blogu, podając więcej szczegółów na ten temat ... –

+0

Głosowałem za zamkniętym pytaniem jako "zbyt subiektywnym", ale potrzebuję 4 dodatkowych głosów aby być zamkniętym :) –