it-swarm.com.de

Was ist der beste Weg, um den Entity Framework-Datenbankkontext (Modell) mit ViewModel in MVVM WPF zu verbinden?

Wie in der obigen Frage: Wie lässt sich das Entity Framework-Datenbankmodell (Kontext) am besten mit viewModel in MVVM (WPF) verbinden?

Ich lerne MVVM-Muster in WPF. Viele Beispiele zeigen, wie ein Modell in viewModel implementiert wird. Modelle in diesen Beispielen sind jedoch nur einfache Klassen. Ich möchte MVVM zusammen mit dem Entity-Framework-Modell verwenden (Base First-Ansatz). Was ist der beste Weg, um das Modell mit viewModel zu verbinden?.

Danke für die Antworten.

//ctor of ViewModel 
public ViewModel()
{ 
db = new PackageShipmentDBEntities(); // Entity Framework generated class

ListaZBazy = new ObservableCollection<Pack>(db.Packs.Where(w => w.IsSent == false)); 
}

Dies ist mein üblicher Ctor von ViewModel. Ich glaube, es gibt einen besseren Weg. Ich habe über das Repository-Muster gelesen und bin mir nicht sicher, ob ich dies an WPF MVVM anpassen kann

9
hal9k2

Ich habe mir das ziemlich genau angesehen und keine "perfekte" Lösung gefunden. Das Repository-Muster funktioniert wunderbar für MVC-Anwendungen, bei denen der Kontext nur von kurzer Dauer ist, da er in einem kurzlebigen Controller vorhanden ist. Das Problem tritt jedoch auf, wenn Sie versuchen, dieselbe Struktur auf eine wpf-App anzuwenden, in der VM = kann über lange Zeiträume bestehen bleiben.

Ich habe diese Lösung in der Vergangenheit verwendet, die viel einfacher ist als viele der Repo-Muster, die ich gesehen habe und die versuchen, Dinge extrem zu abstrahieren, was zu nahezu unlesbaren Mengen an Code führt, die schwer zu debuggen sind. Hier sind die Schritte ...

  1. Erstellen Sie ein separates Projekt, damit EDMX als Datenzugriffsschicht fungiert
  2. Erstellen Sie unter demselben Projekt einen Ordner "Repositorys"
  3. Erstellen Sie eine Basisklasse "BaseRepository" als "Arbeitseinheit". Mit IDisposable können Sie dies in einer using(){} verwenden, und mit partial können Sie andere Repositorys implementieren

    public partial class MyEntityRepository : IDisposable
    {
        MyEntities context = new MyEntities();
    
        public void Dispose()
        {
            context.Dispose();
        }
    }
    
  4. Erstellen Sie eine weitere Datei mit dem Namen "MyOtherRepository". Erstellen Sie dieselbe Teilklasse, implementieren Sie jedoch Methoden basierend auf dem, was diese Datei enthalten soll

    public partial class MyEntityRepository
    {
        public void MyOtherMethodSave(EntityObject obj)
        {
            //work with context
            ...
    
            context.SaveChanges();
        }
    }
    

Jetzt in Ihrem VM können Sie dies tun ...

using(MyEntityRepository repo = new MyEntityRepository())
{
     repo.MyOtherMethodSave(objectToSave);
}

Dadurch werden alle Ihre Repositorys unter einer Klasse zusammengefasst, sodass Sie sich nicht mit einem separaten Kontext befassen müssen. Sie können verschiedene Repos besser verwalten, indem Sie die Methoden in verschiedene Dateien gruppieren, und so verhindern, dass Code dupliziert wird. Darüber hinaus sind Ihre Kontexte so kurzlebig wie ohne dieses Muster.

Der Nachteil ist, dass Sie bei größeren Systemen möglicherweise viele Methoden haben, die unter Ihrem Repo gebündelt werden. Eine Lösung in diesem Fall wäre, einige grundlegende allgemeine Befehle wie "Suchen" oder "Hinzufügen" zu implementieren und spezielle Befehle in ihrem jeweiligen Repository zu implementieren.

4
Shoe

Im Gegensatz zu Repositories, die ich nicht mag. Ich würde empfehlen, das Befehlsmuster zu verwenden, wie von Ayende empfohlen.

Einfach gesagt, erstellen Sie für jede Operation eine separate ThisOperationCommand Klasse. Innerhalb dieser Klasse arbeiten Sie mit normalem EF-Kontext. Sie können sogar eine Basisklasse EFCommand verwenden, die einige Installationsarbeiten für Sie erledigt.

Auf der ViewModel-Seite erstellen Sie eine Instanz dieses Befehls, füllen ihn mit Parametern (Sie können sogar die gesamte ViewModel-Instanz übergeben, wenn Sie nichts gegen eine enge Kopplung zwischen dem Befehl und ViewModel haben) und übergeben ihn dann an eine Art Execute Methode, die den Befehl startet, ausführt, abreißt und dann alles zurückgibt, was der Befehl erhalten hat. Sie können auch mehrere Werte zurückgeben lassen, wenn Sie es nach der Ausführung von der Instanz des Befehls erhalten.

Der Vorteil ist, dass Sie nicht die gesamte Datenzugriffsschicht als Reposotory duplizieren müssen und Befehle wiederverwenden und verfassen können, solange Sie eine einfache Infrastruktur erstellen, um dies zu unterstützen. Zum Beispiel Befehle von anderen Befehlen ausführen.

4
Euphoric

Für einfache Szenarien habe ich Folgendes verwendet:

public class ViewModel : IDisposable {

    private EntitiesContext _context = new EntitiesContext();

    private SomeEntity _model;
    public SomeEntity Model {
       get { return _model; }
    }

    public View(int id) {
        _model = _context.SomeEntity.Find(id);
    }

    private ICommand _saveCommand = new RelayCommand(() => _context.SaveChanges());
    public ICommand SaveCommand {
        get { return _saveCommand; }
    }        

    public void Dispose() {
         _context.Dispose();
    }

}
0
Mike