Code First: Stowarzyszenia niezależne a stowarzyszenia z kluczami zagranicznymi?

Za każdym razem, gdy zaczynam pracę nad nowym projektem i projektuję moje POCOs, mam mentalną dyskusję ze sobą. Widziałem wiele samouczków / próbek kodu, które wydają się faworyzować skojarzenia kluczy obcych :

Stowarzyszenie kluczy zagranicznych

public class Order
{
    public int ID { get; set; }
    public int CustomerID { get; set; } // <-- Customer ID
    ...
}

W przeciwieństwie do niezależnych stowarzyszeń :

Niezależne stowarzyszenie

public class Order
{
    public int ID { get; set; }
    public Customer Customer { get; set; } // <-- Customer object
    ...
}

Pracowałem z NHibernate w przeszłości i używałem niezależnych skojarzeń, które nie tylko czują się bardziej OO, ale także (z leniwymi loading) mają tę zaletę, że dają mi dostęp do całego obiektu Klienta, a nie tylko jego ID. Pozwala mi to na przykład pobrać instancję zamówienia, a następnie wykonać Order.Customer.FirstName bez konieczności jawnego łączenia, co jest niezwykle wygodne.

Podsumowując, moje pytania są następujące:]}
  1. czy są jakieś istotne wady w korzystanie z niezależnych stowarzyszeń? i...
  2. jeśli nie ma żadnych, to co byłoby powodem korzystania z asocjacji kluczy Zagranicznych w wszyscy?
Author: Daniel Liuzzi, 2011-03-12

4 answers

Jeśli chcesz w pełni wykorzystać ORM, na pewno użyjesz Entity reference:

public class Order
{
    public int ID { get; set; }
    public Customer Customer { get; set; } // <-- Customer object
    ...
}

Po wygenerowaniu modelu encji z bazy danych z FKs, zawsze będzie on generował odwołania do encji. Jeśli nie chcesz ich używać, musisz ręcznie zmodyfikować plik EDMX i dodać właściwości reprezentujące FKs. Tak było przynajmniej w ramach Entity Framework v1, gdzie dozwolone były tylko niezależne Stowarzyszenia.

Entity framework v4 oferuje nowy typ stowarzyszenia o nazwie Foreign kluczowe skojarzenie. Najbardziej oczywistą różnicą między asocjacją klucza niezależnego a asocjacją klucza obcego jest klasa porządkowa:

public class Order
{
    public int ID { get; set; }
    public int CustomerId { get; set; }  // <-- Customer ID
    public Customer Customer { get; set; } // <-- Customer object
    ...
}

Jak widać masz zarówno własność FK, jak i odniesienie do podmiotu. Istnieje więcej różnic między dwoma rodzajami skojarzeń:

Niezależne stowarzyszenie

  • jest reprezentowany jako oddzielny obiekt w ObjectStateManager. Ma swój własny EntityState!
  • przy budowaniu Stowarzyszenia zawsze potrzebne są entity z obu końców Stowarzyszenia
  • to Asocjacja jest mapowana w taki sam sposób jak encja.

Stowarzyszenie kluczy zagranicznych

  • nie jest reprezentowany jako oddzielny obiekt w ObjectStateManager. Z tego powodu musisz przestrzegać pewnych specjalnych zasad.
  • kiedy budujesz asocjację, nie potrzebujesz obu końców asocjacji. Wystarczy mieć jednostkę potomną i PK jednostki dominującej, ale wartość PK musi być unikalna. Więc podczas korzystania z asocjacji kluczy obcych należy również przypisać tymczasowe unikalne identyfikatory nowo wygenerowanym podmiotom używanym w relacje.
  • to skojarzenie nie jest mapowane, ale zamiast tego definiuje ograniczenia odniesienia.

Jeśli chcesz użyć asocjacji kluczy obcych, musisz zaznaczyć Dołącz kolumny kluczy obcych w modelu w Kreatorze modelu danych jednostki.

Edit:

Stwierdziłem, że różnica między tymi dwoma rodzajami skojarzeń nie jest zbyt dobrze znana, więc napisałem krótki artykuł opisujący to bardziej szczegółowo i moje własne zdanie na ten temat.

 104
Author: Ladislav Mrnka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-11 09:39:59

Użyj obu. I uczyń swoje odniesienia do obiektu wirtualnym, aby umożliwić leniwe Ładowanie. Tak:

public class Order
{
  public int ID { get; set; }
  public int CustomerID { get; set; }
  public virtual Customer Customer { get; set; } // <-- Customer object
  ...
}

Pozwala to zaoszczędzić na niepotrzebnych wyszukiwaniach DB, pozwala na leniwe ładowanie i pozwala łatwo zobaczyć/ustawić ID, jeśli wiesz, co chcesz, aby to było. Zauważ, że posiadanie obu nie zmienia w żaden sposób struktury tabeli.

 33
Author: Seth Paulson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-11 00:14:01

Niezależne stowarzyszenie nie działa dobrze z AddOrUpdate który jest zwykle używany w Seed metoda. Gdy odniesienie jest już istniejącym elementem, zostanie ono ponownie wstawione.

// Existing customer.
var customer = new Customer { Id = 1, Name = "edit name" };
db.Set<Customer>().AddOrUpdate(customer);

// New order.
var order = new Order { Id = 1, Customer = customer };
db.Set<Order>().AddOrUpdate(order);

W wyniku tego istniejący klient zostanie ponownie wstawiony, a nowy (ponownie wstawiony) Klient zostanie powiązany z nowym zamówieniem.


Chyba że użyjemy asocjacji klucza obcego i przypiszemy id.

 // Existing customer.
var customer = new Customer { Id = 1, Name = "edit name" };
db.Set<Customer>().AddOrUpdate(customer);

// New order.
var order = new Order { Id = 1, CustomerId = customer.Id };
db.Set<Order>().AddOrUpdate(order);

Mamy oczekiwane zachowanie, istniejący klient będzie związany z new order.

 8
Author: Yuliam Chandra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-18 06:19:28

Preferuję podejście obiektowe, aby uniknąć niepotrzebnych poszukiwań. Obiekty właściwości mogą być równie łatwo wypełniane, gdy wywołujesz metodę fabryczną, aby zbudować cały obiekt (używając prostego kodu zwrotnego dla zagnieżdżonych jednostek). Nie ma żadnych wad, które mogę zobaczyć, z wyjątkiem zużycia pamięci (ale można buforować swoje obiekty prawo?). Tak więc wszystko, co robisz, to zastępowanie stosu za stertę i uzyskiwanie zysków z nie wykonywania wyszukiwań. Mam nadzieję, że to ma sens.

 4
Author: CarneyCode,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-12 10:43:13