6

Szukam sposobu dodawania powiązania między dwoma obiektami i posiadania ustawialnego identyfikatora dla klucza obcego. Przeszukałem poprzednie posty, ale najbliżej mogę znaleźć sugestię. Opowiedz o stowarzyszeniu - na co nie mam nadziei. Wiem, że można to zrobić w Entity Framework z wiązaniem .HasForeignKey, ale nie mogę znaleźć sposobu na to w Fluent NHibernate.Fluent NHibernate - mapowanie klucza obcego jako własności

Weźmy dwa przykładowe podmioty:

public class Ticket 
{ 
    public virtual int Id { get; set; } 
    public virtual string Title { get; set; } 
    public virtual string ServiceId { get; set; } 
    public virtual Service Service { get; set; } 
} 

public class Service 
{ 
    public virtual string Id { get; set; } 
} 

Chcę móc utworzyć nową instancję Biletu i przypisać usługi do niego stosując następujące środki (zakładamy, że związane usługi już istnieje w tabeli):

Ticket ticket = new Ticket() { 
    Title = "Problem with MS Word", 
    ServiceId = "Microsoft Word 2012" 
}; 

Co nie chcę zrobić jest następujący:

Ticket ticket = new Ticket() { 
    Title = "Problem with MS Word", 
    Service = Session.Load<Service>("Microsoft Word 2012") 
}; 

mam uzasadnione powody do tego, a jak mówiłem, można to zrobić w Entity Framework, ale jestem bardzo zakłopotany, jak osiągnąć to samo w Fluent NHibernate. Moje mapowania obecnie wyglądają tak:

public class TicketMapping : ClassMap<Ticket> 
{ 
    public TicketMapping() 
    { 
     Id(m => m.Id); 
     Map(m => m.Title).Column("Title"); 
     Map(m => m.ServiceId).Column("ServiceId"); 
     HasOne(m => m.Service).ForeignKey("ServiceId"); 

     Schema("dbo"); 
     Table("Tickets"); 
    } 
} 

public class ServiceMapping : ClassMap<Service> 
{ 
    public ServiceMapping() 
    { 
     Id(m => m.Id); 

     Schema("dbo"); 
     Table("Services"); 
    } 
} 

Każda pomoc zawsze doceniana!


Tylko szybka edycja dla Jay - powodem, dla którego nie chcą Session.Load mój żywioł to dlatego, że nie chcą mojego warstwy prezentacji (MVC 3) wiedząc nic o NHibernate - dlatego m używa wzorca repozytorium i wstrzykuje do kontrolera jedno repozytorium. Tak na przykład, będę mieć TicketRepository która przylega do następnego zamówienia

public interface IRepository<T> 
{ 
    T GetById(object id); 
    void Create(T entity); 
    void Update(T entity); 
    void Delete(T entity); 
} 

nie chcę mieć do wstrzyknąć ServiceRepository również po to, żeby odniesienie do dla SłużbyBilet.

+1

Czy możesz opracować uzasadnione powody, dla których nie chcesz używać 'Session.Load'? – Jay

+1

@Jaj, nie jestem pewien co do przyczyn Terricka ... ale czasami może być śmieszne, aby załadować obiekt tylko po to, aby móc odwołać się do klucza, który masz już przed zapisaniem, IMHO. Mieliśmy ścisłą umowę SLA dotyczącą wcześniejszego projektu, w którym musieliśmy wykonać to samo obejście w Entity Framework, zanim otrzymaliśmy wsparcie FK. –

+0

@Jam zaktualizowałem mój wpis z przyczyn. Poza tym Kevin ma rację, nie chcę dodatkowego obciążenia związanego z ładowaniem innej jednostki dla tego powiązanego. –

Odpowiedz

3

Sposób, w jaki go widzę, tak naprawdę nie można uniknąć używania Session.Load (id) podczas korzystania z NHibernate. Jak wspomniano w komentarzach, to NIE trafi w bazę danych, wystarczy utworzyć obiekt proxy z identyfikatorem.

Niektórymi z możliwych opcji:

  1. wtryskiwać drugą repozytorium rodzajowymi (ServiceRepository) do kontrolera. Naprawdę nie widzę z tym problemu, ale z jakiegoś powodu chcesz tego uniknąć. Możesz dodać metodę LoadById do ogólnego interfejsu i implementować ją inaczej w każdej implementacji dla NH i EF (lub innych). W EF impl ten sposób może działać tak jak GetById, podczas gdy w NH impl wywołuje Session.Load
  2. Implementuje nie ogólne repozytorium dla AR (root agregatu), który w tym przypadku byłby Biletem. Może to oznaczać specyficzne metody ładowania usługi, a także biletu.
  3. Zaimplementuj inną abstrakcję na górze dwóch repozytoriów i wprowadź ją do kontrolera zamiast do dwóch repozytoriów w opcji 1. To może f.Przykładem może być ignorancki UnitOfWork, o którym mowa poniżej: Persistance ignorant UoW, lub jakaś Usługa Aplikacji, która organizuje tworzenie Biletów lub TicketFactory.

Z 3 opcji, opcja 1 jest prawdopodobnie najprostsza, a 3 może zapewnić lepszą abstrakcję i większą łatwość konserwacji w terenie.

+0

Dzięki, że lepiej zrozumiałem 'Session.Load', oznaczało to, że już nie jestem zainteresowany jego używaniem. W efekcie skorzystałem z frameworków entity i zrezygnowałem z NHibernate (głównie dlatego, że jestem bardziej zadowolony z EF, ale chciałem zobaczyć, co NH ma do zaoferowania). –

+0

Rzucił mi się pomysł zamiany moich kluczy obcych na obiekty int, zamiast obiektów, ponieważ nie chciałem mieć trafienia w DB dla każdego obiektu połączonego przy każdym wstawieniu lub aktualizacji ... dopóki nie natknąłem się na to pytanie i nie dowiedziałem się o Session.Load(). Po porównaniu wyników logarytmu nhibernate jeden po drugim dla prostych operacji - wow! OGROMNE oszczędności! Dzięki! – Brett

0

Możesz użyć lewy. Aby zachować swój kod w czystości.

To jest kwestia NH, musisz wdrożyć to rozwiązanie w repozytoriach NH, więc rozwiązuję to w ten sposób.

przed dodać lub zaktualizować

if (!string.IsNullOrEmpty(ServiceId) && Service == null) 
{ 
    Service = new Service{ Id = ServiceId }; 
} 

normalną pracę repozytorium ...

przetestować go i pracy. Twoja architektura nadal jest czysta od decyzji ORM

+0

Załóżmy, że jeśli klasa usługi ma wiele pól, to czy w tym przypadku musimy przypisać tutaj wszystkie pola? w obliczu tego samego problemu ... – jkyadav

Powiązane problemy