Laden...

EF und ASP.Net MVC

Erstellt von topperdel vor 14 Jahren Letzter Beitrag vor 14 Jahren 1.239 Views
T
topperdel Themenstarter:in
67 Beiträge seit 2007
vor 14 Jahren
EF und ASP.Net MVC

Hallo zusammen!

Ich habe ein Problem mit dem Entity Framework und ASP.NET MVC. Ich habe eine einfach Tabelle "Termine" und eine Tabelle "Orte". "Termine" war zuerst da, ich habe die Views für Erzeugen, bearbeiten etc. erstellt. Dann habe ich die "Orte" hinzugefügt und in in der Termine-Tabelle den fremdschlüssel OrtID hinzugefügt, das EF-Model aktualisiert etc.
Das funktioniert.

Was ich aber nicht hinbekomme ist, wie ich auf der Create- und der Edit-View nun eine Dropdownbox anbinde, mit der ich beim Anlegen oder Bearbeiten eines Termins einen Ort verknüpfen kann. Ich kriege alle vorhandenen Orte angezeigt (mittels ViewData) - aber der gewählte Ort lässt sich nicht automatisch mit an den Termin binden.

Wie ist denn da das normale Vorgehen? Ich suche scheinbar unter den falschen Stichworten. Warum kann ich nicht einfach das von EF generierte Feld "Ort" bzw. "OrtReference" auf die ASP-Seite packen und das Framework kümmert sich um die Anzeige einer Dropdownlist incl. entsprechender Übernahme des gewählten Wertes.

Bin für jeden Hinweis dankbar!

Viele Grüße

TopperDEL

270 Beiträge seit 2005
vor 14 Jahren

Hallo topperdel,

sofern du MVC 2 Preview verwendest könnte dir der folgende Link helfen.

Ansonsten könntest du auch eine weiter View schreiben "Edit" und hier das Model mit den entsprechenden Werten versorgen die du benötigst um z.B. die DropDownList anzuzeigen.

mfg Hulk

T
topperdel Themenstarter:in
67 Beiträge seit 2007
vor 14 Jahren
...

Hallo Hulk,

danke für deine Antwort! Leider hilft mir das nicht weiter. Ich verwende das "normale" MVC. Aber die Problemstellung ist, wie ich finde, eine andere.

Vielleicht formuliere ich es mal anders. Wenn ich in einer Tabelle ein Fremdschlüssel einer anderen habe - wie kann ich dann in einer View die erlaubten Werte zur Auswahl bringen? Wie machen das denn alle? Wie kann ich etwa beim Anlegen eines Produkts die Kategorie aus den vorhandenen auslesen? Muss ich das alles selber machen, oder kann das ASP.Net MVC schon out-of-the-box?

Danke weiterhin für jeden Hinweis!

Viele Grüße

TopperDEL

T
topperdel Themenstarter:in
67 Beiträge seit 2007
vor 14 Jahren

Hi!

Ok, ich habe jetzt folgende Lösung gefunden:

Gehen wir davon aus, dass wir ein Tabelle "Products" und eine "Categories" haben. Ein Produkt kann in einer Kategorie sein. Somit hat ein Product eine Navigationseigenschaft "Category".

Beim Erstellen eines Products muss ich nun zunächst die vorhandenen Kategorien zur Verfügung stellen:


public ActionResult Create()
        {
            ViewData["Categories"] = entities.CategoryMenge;
            return View();
        } 

In der CreateView kann ich jetzt die vorhandenen Kategorien anzeigen:


<p> 
               <label for="Category.CategoryID">Kategorie:</label>
               <%= Html.DropDownList("Category.CategoryID", new SelectList((IEnumerable)ViewData["Categories"], "CategoryID", "Name"))%>
            </p>

Beim submit muss nun folgendes geschehen:


[AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Create([Bind(Exclude = "ProductID")] Product productToCreate)
        {
            try
            {
		//Kategorie explizit nachlesen
                productToCreate.Category = entities.CategoryMenge.First(c => c.CategoryID == productToCreate.Category.CategoryID);
                entities.AddToProductMenge(productToCreate);
                entities.SaveChanges();
                return RedirectToAction("Index");
            }
            catch
            {
                return View();
            }
        }

Die Kategorie wird von der Dropdownlist nur als einfacher int-Wert in das Id-Feld geschrieben. Die Navigationseigenschaft bekommt dadurch aber noch nicht die "echte" Kategorie zugewiesen. Daher wird sie zunächst noch mal neu eingelesen. Anschließend wird das Produkt hinzugefügt.

Beim Editieren eines Produktes läuft es nun so ab:


public ActionResult Edit(int id)
        {
	    //Produkt zur ID lesen
            Product product = entities.ProductMenge.First(p => p.ProductID == id);
            product.CategoryReference.Load();
            SelectList list = new SelectList(entities.CategoryMenge, "CategoryID", "Name", product.Category);
            ViewData["Categories"] = list;
            return View(product);
        }

Damit die beim Produkt eingetragene Kategorie auch als selektierter Wert in der DropDownList angezeigt wird, muss ich die SelectList händisch aufbauen und den selektierten Wert vorgeben. Außerdem muss sichergestellt werden, dass die Navigationseigenschaft "Category" von Product auch wirklich geladen wurde (Load()).

Die View sieht wie folgt aus:


<p> 
               <label for="Category.CategoryID">Kategorie:</label>
               <%= Html.DropDownList("Category.CategoryID", new SelectList((IEnumerable)ViewData["Categories"], "Value", "Text"))%>
            </p>

Und das eigentliche Editieren funktioniert so:


[AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Edit(Product productToEdit)
        {
            try
            {
                // TODO: Add update logic here
		//Product neu lesen, da das übergebene Produkt vom Kontext völlig abgekoppelt ist
                Product existingProd = entities.ProductMenge.First(p => p.ProductID == productToEdit.ProductID);
                existingProd.Name = productToEdit.Name;
                existingProd.Category = entities.CategoryMenge.First(c => c.CategoryID == productToEdit.Category.CategoryID);
                entities.ApplyPropertyChanges(existingProd.EntityKey.EntitySetName, existingProd);
                entities.SaveChanges();
                
                return RedirectToAction("Index");
            }
            catch (Exception ex)
            {
                return View();
            }
        }

Hier habe ich keine bessere Möglichkeit gefunden. Das beim HTTP-Post übergebene Produkt ist vom Entity Framework-Kontext völlig losgelöst (detached) - daher lese ich es noch einmal über die Id aus dem Kontext und setze alle in der View editierbaren Eigenschaften noch mal neu. Dann übernehme ich die Änderungen. Anders habe ich es nicht hinbekommen, aber so funktionierts.

Erscheint mir alles sehr aufwändig für den normalen Fall, dass ich Fremdschlüsselwerte an einem Objekt ändern will. Geht das nicht komfortabler? Hab ich was übersehen? Hat jemand Verebsserungsideen?

Viele Grüße

TopperDEL