Do tej pory cały nasz kurs, oparty było tylko jedną tabelę. Najwyższa pora, aby to zmienić, dodamy dziś nową klasę, która będzie symulować… przeglądy w posiadanych autach. W osiągnięciu tego celu pomoże nam dodatkowy model oraz kilka modyfikacji w istniejącym już kodzie. Naszym zadaniem jest uzyskanie standardowej, bazodanowej relacji jeden do wielu (jeden samochód, wiele przeglądów).
Dodanie nowego modelu
Pierwszym krokiem w dzisiejszym artykule jaki wykonamy, będzie dodanie nowej publicznej klasy do folderu Models (Service.cs):
using System; namespace Samochody.Models { public class Service { public int Id { get; set; } public DateTime Date { get; set; } public string Comment { get; set; } public int CarID { get; set; } public virtual Car Car { get; set; } } }
Jak wspomniałem wcześniej, nowa klasa będzie odpowiedzialna za przechowywanie danych o przeglądach, które przeszedł konkretny samochód. Widzimy tutaj pole CarID, które stanowi wiązanie do tabeli Cars.
Konstrukcja:
public virtual Car Car { get; set; }
to tzw. navigation property, która definiuje relację oraz stanowi „okno” do sąsiedniego modelu.
Foreign Key
W tym momencie zajmiemy się aktualizacją modelu Cars. Założyliśmy, że samochód może mieć wiele przeglądów, a więc jest to relacja jeden do wielu (naturalnie oznacza to, że konkretny przegląd, może być identyfikowany, tylko z jednym autem). Relację jeden do wielu w Entity Framework odwzorowujemy według poniższego schematu:
public virtual ICollection<Service> Services { get; set; }
virtual – dzięki temu atrybutowi, do tego pola zostanie zastosowane tzw. lazy loading. Oznacza to, że dane dla tego pola zostaną wczytane, dopiero wtedy, gdy się do nich odwołamy.
ICollection<Service> Services – interfejs ICollection pozwala na określenie relacji jeden do wielu, dzięki niemu samochód, będzie mógł odwoływać się do wielu krotek z tabeli Services. Gdybyśmy definiowali relację jeden do jeden, należałoby oczywiście opuścić interfejs ICollection, pozostawiający tym samym klasę Service, identycznie jak w modelu Service. Dalszy człon to nazwa pola.
Otwórzmy sobie jeszcze drzwi do tabeli Services, dodając w klasie CarDBCtxt nowy obiekt DbSet:
public class CarDBCtxt : DbContext { public DbSet<Car> Cars { get; set; } public DbSet<Service> Services { get; set; } }
W tym momencie nie możemy, korzystać z serwisu, ponieważ model jest niekompatybilny z bazą. Moglibyśmy usunąć bazę i wygenerować ją na nowo, ale zamiast tego zrobimy na niej update.
Update bazy danych
Otwieramy Package Manager Console:

Package Manager Console – Kurs ASP.NET MVC 5
Najpierw zezwalamy na migrację w naszym projekcie:
Enable-Migrations -ContextTypeName Samochody.Models.CarDBCtxt
Następnie:
add-Migration NowyModel update-database
Dodanie kontrolera
Z pomocą Entitfy Framework dodajmy nowy kontroler dla modelu Service. Klikamy prawym przyciskiem myszy w folder Controllers, wybieramy Add > Controller, a następnie:

Dodanie kontrolera – Kurs ASP.NET MVC 5
wskazujemy klasę Service, jaką tą, dla której chcemy wygenerować CRUD.
Dodajmy kilka wartości za pomocą akcji Create, wygenerowanego przed chwilą kontrolera.

Tabela Services – Kurs ASP.NET MVC 5
W tej chwili mam w bazie danych kilka samochodów oraz dowiązane do nich przeglądy. Nie zaimplementowaliśmy jeszcze wyświetlania tych przeglądów. Zróbmy to np.: w widoku Cars2/Details:
<p>Przeglądy:</p> @foreach (var item in Model.Services) { <p>@item.Date - @item.Comment</p> }
Powyższy kawałek kodu, przechodzi po kolekcji, która przechowuje wiązania do przeglądów i wyświetla żądane dane. Tak to wygląda w praktyce:

Widok Details – Kurs ASP.NET MVC 5
Podsumowanie
Pokrótce przejrzeliśmy dzisiaj relację jeden do wielu, dzięki dodaniu dodatkowej tabeli do naszego projektu. Dzięki Entity Framework praca przebiega w dużej mierze automatycznie, co niweluje miejsce, gdzie możemy popełnić błąd. Zrozumienie tego zagadnienia jest kluczowe dla projektowania złożonych systemów w technologii ASP.NET, dlatego odsyłam do dokumentacji/poradników Microsoftu, aby wystarczająco zgłębić wiedzę.
Wpis jest częścią kursu ASP.NET MVC 5.