Qual è il modo migliore per collegare il contesto del database Entity Framework (modello) a ViewModel in MVVM WPF?

9

Come nella domanda precedente: qual è il modo migliore per cablare il modello di database Entity Framework (contesto) per viewModel in MVVM (WPF)?

Sto imparando lo schema MVVM in WPF, un sacco di esempi mostra come implementare il modello in viewModel, ma i modelli in quegli esempi sono solo classi semplici, voglio utilizzare MVVM insieme al modello di struttura dell'entità (primo approccio di base). Qual è il modo migliore per collegare il modello a viewModel.

Grazie per le risposte.

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

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

Questo è il mio solito ctor di ViewModel, penso ci sia un modo migliore, stavo leggendo sul pattern del repository, non sono sicuro di poterlo adattare a WVF MVVM

    
posta hal9k2 04.10.2013 - 13:04
fonte

3 risposte

4

Ho esaminato un po 'questo aspetto e non ho trovato una soluzione "perfetta". Il modello di repository funziona meravigliosamente per le applicazioni MVC in cui il contesto è di breve durata perché esiste in un controller di breve durata, ma il problema si verifica quando si tenta di applicare la stessa struttura a un'app wpf in cui la VM può persistere per lunghi periodi di tempo.

Ho usato questa soluzione in passato, che è molto più semplice di molti dei pattern pronti contro termine che ho visto in questo tentativo di astrarre le cose ad un livello estremo, risultando in quantità quasi illeggibili di codice che sono difficili da debugare. Ecco i passaggi ...

  1. Crea un progetto separato per EDMX per agire come livello di accesso ai dati
  2. Crea una cartella "Repository" sotto lo stesso progetto
  3. Crea una Base class "BaseRepository" per agire come "Unità di lavoro". IDisposable ti consentirà di utilizzarlo in using(){} e partial ti consentirà di implementare altri repository

    public partial class MyEntityRepository : IDisposable
    {
        MyEntities context = new MyEntities();
    
        public void Dispose()
        {
            context.Dispose();
        }
    }
    
  4. Crea un altro file chiamato "MyOtherRepository". crea la stessa classe parziale ma implementa metodi basati su ciò che vuoi che quel file contenga

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

Ora nella tua VM puoi farlo ...

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

Questo raggruppa tutti i repository sotto una classe in modo da non dover gestire un contesto separato. Ti consente di gestire meglio diversi repository raggruppando i metodi in file diversi e aiuta a prevenire la duplicazione del codice. Inoltre, i tuoi contesti hanno una vita breve come lo erano senza utilizzare questo modello.

Lo svantaggio è che con sistemi più grandi, potresti avere molti metodi che vengono raggruppati nel tuo repository. Una soluzione in tal caso sarebbe implementare alcuni comandi comuni di base come "Trova" o "Aggiungi" e implementare quelli specializzati nei rispettivi repository.

    
risposta data 24.10.2013 - 07:10
fonte
4

Contro i depositi, cosa che non mi piace. Vorrei raccomandare l'uso del comando Command, come raccomandato da Ayende .

Detto semplicemente, per ogni operazione, crei una classe ThisOperationCommand separata. All'interno di questo corso lavorerai con il normale contesto EF. Potresti anche utilizzare qualche classe di base EFCommand che fa un po 'di impianto idraulico per te.

Da ViewModel, puoi creare l'istanza di questo comando, riempirlo con i parametri (puoi anche passare l'intera istanza ViewModel se non ti interessa l'accoppiamento stretto tra il comando e ViewModel) e poi passarlo a qualche tipo di Execute metodo, che avvierà il comando, lo eseguirà, lo abbatterà e poi restituirà qualunque cosa il comando abbia ottenuto. Puoi anche farlo restituire più valori se lo ottieni dall'istanza del comando dopo l'esecuzione.

Il vantaggio è che non è necessario duplicare l'intero livello di accesso ai dati come repository ed è possibile riutilizzare e comporre comandi purché si crei una semplice infrastruttura per supportarla. Ad esempio, eseguendo comandi da altri comandi.

    
risposta data 24.10.2013 - 08:33
fonte
0

Per scenari semplici ho usato quanto segue:

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();
    }

}
    
risposta data 26.10.2013 - 04:51
fonte

Leggi altre domande sui tag