Ostatni tydzień spędziłem nad czytaniem o EF i relacjach, które chciałbym wykorzystać w swojej pracy inżynierskiej korzystającej z Entity Framework. Nawet założyłem temat w którym zapytałem się czy dobrze ułożyłem relacje pomiędzy klasami. Jako że mi to nie działało tak jak chciałem postanowiłem że zrobię sobie jakiś mały przykład i na nim potrenuje relacje. No i okazało się że chyba nie rozumiem jak się tego używa i po co :( tydzień za tygodniem leci czasu na dokończenie pracy coraz mniej a ja jeszcze sporo mam do zrobienia.
Do rzeczy.
Mam dwie klasy z relacją one-to-many
public class Artist
{
public int ArtistID { get; set; }
[Required]
public string Name { get; set; }
public virtual List<Album> Albums { get; set; }
}
public class Album
{
public int AlbumID { get; set; }
[Required]
public string Title { get; set; }
public int ArtistID { get; set; } //ForeignKey
public virtual Artist Artist { get; set; } ///navigation property
}
I teraz tworzę sobie ArtistController
w którym chcę mieć możliwość dodawania nowych artystów(Create
) a następnie mieć możliwość dodania do nich albumów(CreateAlbum
).
public class ArtistController : Controller
{
MusicContext context = new MusicContext();
//wyświetlenie wszystkich artystów
public ActionResult Index()
{
return View(context.Artists.ToList());
}
//dodanie nowego artysty
public ActionResult Create()
{
Artist artist = new Artist();
return View(artist);
}
[HttpPost]
public RedirectToRouteResult Create(Artist artist)
{
context.Artists.Add(artist);
context.SaveChanges();
return RedirectToAction("Index");
}
//Informacje o Artyście - widzę tutaj jakie Albumy należą do tego artysty i mogę dodać nowe.
public ActionResult Details(int id)
{
var listOfArtists = context.Artists.ToList();
Artist artist = listOfArtists.FirstOrDefault(a => a.ArtistID == id);
return View(artist);
}
public ActionResult CreateAlbum(int id)
{
Artist artist = context.Artists.FirstOrDefault(a => a.ArtistID == id);
ViewBag.artist = artist;
Album album = new Album();
return View(album);
}
[HttpPost]
public RedirectToRouteResult CreateAlbum(Album album)
{
context.Albums.Add(album);
context.SaveChanges();
return RedirectToAction("Index");
}
}
Tak wygląda widok Details
w którym tworzę ActionLink
do metody akcji CreateAlbum
żeby dodać nowy album do już istniejącego artysty.
@model RelationshipsPractice.Models.Artist
@{
ViewBag.Title = "Details";
}
<h2>Details</h2>
<h3>@Html.ActionLink("Add Album", "CreateAlbum", new { id = Model.ArtistID })</h3>
<fieldset>
<legend>Artist</legend>
<div class="display-label">
@Html.DisplayNameFor(model => model.Name)
</div>
<div class="display-field">
@Html.DisplayFor(model => model.Name)
</div>
<h4>Albums</h4>
<ul>
@foreach (var album in Model.Albums)
{
<li>@album.Title</li>
}
</ul>
</fieldset>
<p>
@Html.ActionLink("Edit", "Edit", new { id = Model.ArtistID })
@Html.ActionLink("Back to List", "Index")
</p>
I tutaj mój widok CreateAlbum
@model RelationshipsPractice.Models.Album
@{
ViewBag.Title = "CreateAlbum";
}
<h2>CreateAlbum</h2>
@{ Model.Artist = ViewBag.artist; }
@using (Html.BeginForm()) {
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<fieldset>
<legend>Album</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Title)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Title)
@Html.ValidationMessageFor(model => model.Title)
</div>
@Html.HiddenFor(x => x.Artist)
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
Jeżeli chcę to zrobić w ten sposób to dostaje błąd
{"The INSERT statement conflicted with the FOREIGN KEY constraint \"FK_dbo.Albums_dbo.Artists_ArtistID\". The conflict occurred in database \"RelationshipsTest\", table \"dbo.Artists\", column 'ArtistID'.\r\nThe statement has been terminated."}
Zresztą zdaję sobie sprawę że robię to źle. I tu moja prośba, żeby ktoś mi powiedział jak ja mam to zrobić na tym prostym przykładzie, żeby to działało a jednocześnie korzystało z tych relacji jakkolwiek ma to z tego korzystać.