Hab ich ehrlich gesagt nie daran gedacht, dass ich ja die inputs/labels/displays auch komplett selbst generieren kann. Obwohl ich andere HTML sachen ja bereits komplett selbst generiere 🙈.
Manchmal ist man so auf eine Methode versteift, dass man gar nicht erst daran denkt es auf andere Art zu versuchen.
Ich werd mir das mal ansehen.
Wie dann die id und name tags der HTML Elemente gesetzt werden müssen, dass dann das Model Binding noch funktioniert, muss ich mir noch ansehen. Das steht aber sicher in der Doku.
Danke für deine Antwort und deine Anregung das komplett anders zu machen.
Ich habe das Problem, dass die IHtmlHelper.Display Methode bei mir nicht mit Collections funktioniert.
Ich habe in meinem View folgenden Code:
@for (var index = 0; index < Model.Products.Count; index++)
{
@Html.DisplayFor(m => m.Products[index].Id)
@Html.Display($"Products[{index}].Id")
}
Die DisplayFor Methode funktioniert einwandfrei.
Die Display Methode kann nicht mit dem Index-Operator umgehen, sondern gibt nichts aus.
Ist das "Works as Designed", oder mache ich hier irgendwo einen Fehler?
Das Model der oben erwähnten View sieht folgendermaßen aus:
public class ProductsViewModel
{
public List<Product> Products { get; set; }
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
}
Falls sich jemand fragt warum ich nicht einfach die DisplayFor Methode verwende:
Ich habe einen TagHelper indem ich nur die die nicht-generische IHtmlHelper Komponente verwenden kann.
Der obige Code dient nur dazu mein Problem besser darzustellen.
ich würde so gut es geht, vermeiden in der DB Logik abzubilden.
Das ist meiner Ansicht nach schwer zu Testen und irgendwie ja auch nicht die Aufgabe einer DB.
Vielleicht kurz zum Hintergrund:
Es ist eine Anwendung zur Abwicklung eines Fahrradbasars.
Die läuft nur in einem lokalen Netzwerk mit maximal 20 Usern, daher würde ich Perfomance nicht so kritisch einstufen.
Grundsätzlich läuft das ganze auch schon und ist stabil.
Ich aber bin gerade dabei die Anwendung von simplen Razor Pages auf MVC zu portieren.
Hauptsächlich weils mir Spaß bereitet und ich will etwas Erfahrung sammeln und was neues Lernen.
Also bin ich auch für komplett andere Ansätze offen.
So nun zum Thema Routing:
Das heißt ich habe Zentral eine Stelle wo ich meine Magic-Strings definiere (z.B. als Konstanten).
In der Anwendung verwende ich dann, wenn ich einen Link benötige (UI, oder in einem Controller) den LinkGenerator.
Wobei ich dann ExtensionMethods für den LinkGenerator habe, welche mir meine spezialitäten abdecken.
In meinen Controllern rufe ich dann nur die simple Redirect(string url) Methode auf.
In meinen Views verwende ich dann anstatt dem AnchorTagHelper direkt <a href="....">.
Habe ich das so richtig verstanden?
Was mir dabei halt nicht so gefällt ist, dass ich dann die ExtensionMethods immer mit meinen Controllern abgleichen muss.
Zum Thema mit dem Delegate:
Das mit dem Delegate anstatt der Func war mein erster Ansatz, das kompiliert mir aber nicht: CS1662 CS0428
Zum Thema generische Klasse:
Jo das würde so gehen, aber da finde ich die nameof Syntax noch schöner.
Wenn aber Expressions teuer sind, dann kann ich in diesem Fall auch darauf verzichten.
An manchen Stellen kommt man eh nicht drumrum (z.B. in den Views)
Ich denke ich werde mir das mit dem Routing mal näher ansehen, das ist bisher eh noch ein weißer Fleck auf meiner ASP.NET Landkarte
ich versuche gerade in meiner ASP.NET Core Anwendung die ganzen Magic-Strings, welche im Zusammenhang mit Controller und Action Namen auftreten, zu refaktorisieren.
Bisher habe ich das immer so gemacht:
RedirectToAction<ProductsController>(nameof(ProductsController.Details), new { id = 1234 });
Den Controller Namen hole ich mir dabei über eine Helper-Methode:
public static string ControllerName<TController>() => typeof(TController).Name.TrimEnd("Controller");
Ich würde in Zukunft jedoch gerne so etwas in der Art aufrufen können:
RedirectToAction<ProductsController>(pc => pc.Details, new { id = 1234 });
Dabei habe ich aber Probleme dass ich dann für jede mögliche Action-Methoden-Signatur eine Überladung bereitstellen müsste.
Also so:
Das mit den Commands sieht auch ganz interessant aus, damit muss ich mich mal näher beschäftigen.
Hast du da vielleicht noch weiterführende Lektüre bei der Hand?
Danke Abt, für diese tolle Einführung in das Thema Projections!
Das ist ja eine super Sache, ich wünschte ich hätte mal wieder etwas mehr Zeit mich um mein privates EF Core Projekt zu kümmern.
Nur damit ich das auch richtig verstanden habe:
Ich mache mir also für die verschiedensten Anwendungsfälle (Logik oder UI) einfach meine Projections und das dafür notwendige Profile. Und in der Logik bzw. UI verweise ich dann nur noch auf die Projections. In der UI habe ich dann eventuell noch eine Art ViewModel darum.
Könnte man sagen eine Entity wäre ein Objekt auf Datenbank Ebene und eine Projection wäre dann ein Business Object?
Edit:
Wie wäre das dann wenn ich Daten verändern möchte?
Projections oder auch die KeylessEntity werden ja nicht getrackt.
Wobei ich ja bei Änderungen sowieso im Zweifelsfall mehrer Queries machen muss.
@Abt
Keyless Entity Types kannte ich noch gar nicht, danke für den Hinweis. Damit kann ich in meinem privaten Projekt wo ich EF Core verwende sicher einige Query-Konstrukte optimieren.
Vielleicht noch zum Hintergrund:
Wir haben in der Firma eine Art "ORM" Framework im Einsatz, das aktuell so konfiguriert ist, dass man die Spalten die man haben möchte immer explizit angeben muss. Die Objekte auf die das gemappt wird sind jedoch immer die selben, egal ob ich eine oder alle Spalten einer Tabelle haben will.
Da es in diesem Framework keine Zentrale Stelle gibt wo Daten aus der DB geladen werden, sondern das quer über die komplette Anwendung verstreut ist, bedeutet das einen riesigen Wartungsaufwand.
Daher disktutieren wir aktuell ob wir das Framework nicht umkonfigurieren sodass immer alle Spalten geladen werden.
Darum habe ich hier diesen Thread eröffnet, da ich mir unsicher war ob das generell eine schlechte Idee ist.
Unser "ORM" arbeitet so dass die Spalten im resultierenden SQL explizit angegeben werden. Also denke ich sollten wir das einfach mal testen wie hier die Performance aussieht.
Wenn ich explizit "alle" Spalten abrufe dann ist das besser als * weil ich (bzw. der ORM) die Kontrolle habe was abgefragt wird.
Der ORM könnte ja nicht von allen Spalten wissen.
Die SELECT * Problematik ist also nicht die dass alle Spalten einer Tabelle abgefragt werden, sondern wo die Kontrolle liegt welche Spalten abgefagt werden.
vor ein paar Monaten gab es in einem Thread hier im Forum die Empfehlung dass "SELECT * " eine schlechte Idee ist:
Es wurde dort auch auf StackOverflow verwiesen warum genau das eine schlechte Idee ist.
Ich verstehe soweit die auf StackOverflow genannten Gründe und finde sie klingen auch nachvollziehbar.
Was ich nicht verstehe, ist jedoch wie das zusammen mit einem Object-Relational-Mapping (ORM) Framework verträgt.
Angenommen ich habe eine Klasse die mir eine Tabelle abbildet.
Wenn jetzt beim SELECT aus der Datenbank nicht alle Spalten abgefragt werden, dann ist ja auch mein Objekt nur zum Teil mit den Daten initialisiert.
Woher soll das ORM Framework wissen welche Spalten es abfragen soll?
Dann müsste ja die Logik, welche mit den Datenobjekten arbeitet (oder mit Objekten die daraus aufgebaut sind) der Datenschicht mitteilen welche Spalten sie benötigt.
Da kann ich mir das ORM Framework ja komplett sparen.
Habe ich da etwas falsch verstanden?
Oder ist das ein Problem, dass ich je nach Tabelle anders lösen muss.
in deinem Codebeispiel liegt das Problem daran, dass du nach dem Erzeugen mit new der Referenz jedoch "this.actualMember" zuweist. Somit fügst du jedes mal das gleiche Objekt hinzu.
Die EF Runtime erkennt das und speichert dann nur eines.
Wenn ich dich recht verstehe möchtest du Kopien von Objekten hinzufügen.
Das Kopieren (clonen) musst du selbst implementieren.
class Member
{
Member Clone()
{
return new Member
{
a = this.a,
b = this.b,
c = this.c
// ID hier nicht setzen
};
}
}
foreach(var newMember in members)
{
var member = this.actualMember.Clone();
member.name = "change values";
//set null not allowed for unique id long
//member.id = null;
db.MemberActivations.Add(member);
}
ich hänge gerade an einem Problem wo ich nicht weiß wie ich das lösen soll.
Verwendete Technologie: ASP .NET Core 2.2 Razor Pages
Ich habe eine Page. Auf dieser Page ist ein form. Im form gibt es 2 partial views, welche inputs enthalten.
Beide partial views haben je ein anderes Property des PageModel als Model, sind jedoch vom selben Datentyp.
Wird die Page angezeigt passt noch alles.
Im OnPost haben jedoch beide Properties des Page Models die selben Werte.
Wie löse ich das am besten?
Ich habe ja ein partial view weil ich keinen Code duplizieren will.
Zur besseren Veranschaulichung hier noch etwas Code:
Das PageModel:
public class Ship
{
public string Name { get; set; }
public string Crew { get; set; }
}
public class IndexModel : PageModel
{
[BindProperty]
public Ship FirstShip { get; set; }
[BindProperty]
public Ship SecondShip { get; set; }
public void OnGet()
{
FirstShip = new Ship
{
Name = "USS Enterprise",
Crew = "200-500"
};
SecondShip = new Ship
{
Name = "USS Voyager",
Crew = "150"
};
}
public void OnPost()
{
// FirstShip und SecondShip have the same values
}
}
ein StackPanel ist immer so groß wie sein Inhalt. Da die ListBox verwendet intern ein ItemControl welches sich wie ein StackPanel verhält. Somit sieht es für die ListBox so aus als ob genügend Platz vorhanden ist und es werden keine ScrollBars angezeigt.
Ich kann ebenso wie du auch schon geschrieben hast nur empfehlen ein anderes Container Control zu verwenden.
Auf Anhieb fallen mir 2 Möglichkeiten ein:
-Du schickst der laufenden Anwendung eine Nachricht damit sich diese in den Vordergrund bringt
-Du suchst das Handle des Fensters der laufenden Anwendung und bringst dies in den Vordergrund
Um einen Win32 Aufruf kommst du meines Wissens nach nicht rum.