Autor Beitrag
mygil
Hält's aus hier
Beiträge: 1



BeitragVerfasst: Di 28.02.12 09:22 
Hallo!

Bin Neuling mit dem Entity Framework und stehe vor dem folgenden Problem:

Und zwar habe ich ein Grid in dem alle meine Bestellungen angezeigt werden und einen Button: [Bearbeiten] der wiederum eine zweite Form öffnet.
Mit der zweiten Form soll der Benutzer die ausgewählte Bestellung bearbeiten können.

Wie genau mache ich das jetzt am besten?

Hier mal meine Gedanken:
A) Ich übergebe der zweiten Form das Entity Objekt "Bestellung" mit und verwende Databinding.
Nachteil: Der Benutzer hat ja nach dem ändern der Bestellung noch nicht Wahl zwischen: [Speichern] oder [Abbrechen].
Mache ich das ganze aber mit Databinding, dann ändere ich die Entität sofort und beim [Abbrechen] muss diese wieder "mühselig" zurückgesetzt werden:
ausblenden C#-Quelltext
1:
2:
            if (this.ShowDialog() == System.Windows.Forms.DialogResult.Cancel)
     context.Refresh(System.Data.Objects.RefreshMode.StoreWins, bestellung);

Des weiteren glaube ich, dass man die Entitäten erst dann beschreiben soll, wenn auch wirklich die Daten geändert werden sollen.

B) Ich übergebe der zweiten Form das Entity Objekt "Bestellung" mit und verwende NICHT Databinding.
Vorteil: Ich schreibe die Werte erst dann auf die Entität sobald auf [Speichern] geklickt wird.
Nachteil: Wie kann ich jetzt aber in der zweiten Form die Master-Details anzeigen und bearbeiten lassen?
Wenn ich z.b. eine Bestellposition lösche, dann weiß dass meine Entität anschließend nicht!

Im Anhang ein Screenshot der Beispiel-Anwendung.


Vielen Dank für eure Hilfe!
Einloggen, um Attachments anzusehen!
rittergig
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 33



BeitragVerfasst: Fr 30.03.12 20:50 
Mir fällt spontan auch keine perfekte Möglichkeit ein.
Ich denke es ist am elegantesten, das Objekt zu kopieren.
Also öffnet der Nutzer die Bestellung, wird eine neue Bestellungs-Instanz erzeugt, in der du alle Properties incl. ID kopierst.
Diese übergibst du der Form und bindest du dort an die Controls.
Klickt der Nutzer auf "Speichern", kopierst du die Properties wieder manuell (anhand der ID ausmachen).

A) Entweder du kopierst mnanuell:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
var cloneOfSelectedBestellung = new Bestellung()
{
  Prop1 = selectedBestellung.Prop1,
  Prop1 = selectedBestellung.Prop2,
  ...
  PropN = selectedBestellung.PropN,
}


B) Du suchst nach eine Klasse, die ein Objekt vollständig kopiert (notfalls geht auch: serialisieren als String und wieder deserialisieren)
oder schreibst dir selber eine Klasse, die ein beliebiges Objekt in allen public Properties kopiert (mit Reflections).

C) Du trennst die ausgewählte Bestellung irgendwie vom DataContext, kannst dann beliebig unabhängig bearbeiten.
Und nach Speichern fügst du die Bestllungs-Entität wieder dem Context an.
(irgendwie habe ich schon mal gelesen, dass sowas geht)

Grüße, Peter
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4799
Erhaltene Danke: 1059

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Sa 31.03.12 10:08 
Hallo ihr beiden,

empfehlen kann ich dafür den AutoMapper. Eine Übersicht über die Features (sowie ein GettingStarted) gibt es unter github.com/AutoMapper/AutoMapper/wiki.

Die Datenschicht sollte niemals direkt die EF-Entity-Objekte nach oben geben, sondern möglichst mit sog. DTOs (Data Transfer Objects) arbeiten, welche dann in der Business- und der GUI-Schicht benutzt werden. Erst beim Aufruf der Save-Methode (der Datenschicht) sollte dann das übergebene DTO-Objekt wieder in das EF-Entity-Objekt (ebenfalls mittels AutoMapper) konvertiert werden und dann kann es in der DB abgespeichert werden (Insert oder Update).

Generell fällt diese Vorgehensweise unter "Unit Of Work", s. z.B. blogs.msdn.com/b/ado...y-framework-4-0.aspx
Anstatt DTO wird der Begriff POCO (plain old CLR objects) verwendet, welcher aber das gleiche meint. Eine Übersicht dazu gibt es unter Arbeiten mit POCO-Entitäten (Entity Framework)

P.S. POCO wird in diesem Zusammenhang deshalb manchmal auch "Persistence ignorance CLR objects" genannt.

Edit: Welchen dieser zwei Wege du gehst (AutoMapper oder Repositoy) mußt du selber entscheiden. Für große Projekte kann man selbstverständlich auch beide kombinieren (ich habe mir dafür z.B. ein Programm namens Code-Creator geschrieben, welcher den Mapping-Code für mich erzeugt).