web-dev-qa-db-ja.com

Entity Frameworkデータベースコンテキスト(モデル)をMVVM WPFのViewModelに接続する最良の方法は何ですか?

上記の質問のように:Entity Frameworkデータベースモデル(コンテキスト)をMVVM(WPF)のviewModelに接続する最良の方法は何ですか?

私はWPFでMVVMパターンを学習しています。多くの例は、viewModelにモデルを実装する方法を示していますが、その例のモデルは単純なクラスであり、エンティティフレームワークモデル(ベースファーストアプローチ)と一緒にMVVMを使用したいと思います。モデルをviewModelにワイヤリングする最良の方法は何ですか。

回答ありがとうございます。

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

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

これは私のViewModelの通常の俳優です。もっと良い方法があると思います。リポジトリパターンについて読んでいましたが、これをWPF MVVMに適応できるかどうかわかりません

9
hal9k2

私はこれをかなり調べましたが、「完璧な」解決策は見つかりませんでした。リポジトリパターンは、コンテキストが短命のコントローラーに存在するため短命であるMVCアプリケーションでうまく機能しますが、VMであるwpfアプリに同じ構造を適用しようとすると、問題が発生します=長期間続くことがあります。

私は過去にこのソリューションを使用しましたが、これは、極端な量まで抽象化しようとする多くのレポパターンよりもはるかに単純で、デバッグが困難なほぼ読み取り不可能な量のコードをもたらします。手順は次のとおりです...

  1. EDMXがデータアクセスレイヤーとして機能する別のプロジェクトを作成する
  2. 同じプロジェクトの下に「リポジトリ」フォルダを作成します
  3. 「作業ユニット」として機能する基本クラス「BaseRepository」を作成します。 IDisposableはこれをusing(){}で使用できるようにし、partialは他のリポジトリを実装できるようにします

    public partial class MyEntityRepository : IDisposable
    {
        MyEntities context = new MyEntities();
    
        public void Dispose()
        {
            context.Dispose();
        }
    }
    
  4. 「MyOtherRepository」という別のファイルを作成します。同じ部分クラスを作成しますが、ファイルに含める内容に基づいてメソッドを実装します

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

VMでこれを行うことができます...

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

これにより、すべてのリポジトリが1つのクラスにグループ化されるため、個別のコンテキストを処理する必要がありません。メソッドをさまざまなファイルにグループ化することで、さまざまなリポジトリをより適切に管理でき、コードの重複を防止できます。その上、コンテキストは、このパターンを使用しない場合と同じように短命です。

欠点は、大規模なシステムでは、リポジトリの下にバンドルされる多くのメソッドがある可能性があることです。その場合の1つの解決策は、「検索」や「追加」などのいくつかの基本的な一般的なコマンドを実装し、それぞれのリポジトリに専用のコマンドを実装することです。

4
Shoe

リポジトリには反対ですが、私は好きではありません。 Ayende で推奨されているように、コマンドパターンの使用をお勧めします。

簡単に言うと、各操作に対して、個別のThisOperationCommandクラスを作成します。このクラスでは、通常のEFコンテキストで作業します。いくつかの基本クラスEFCommandを使用することもできます。

ViewModel側から、このコマンドのインスタンスを作成し、パラメーターを入力して(コマンドとViewModelの間の密結合を気にしない場合は、ViewModelインスタンス全体を渡すこともできます)、それをある種のExecuteメソッドに渡します。コマンドを起動して実行し、破棄してから、取得したコマンドを返します。実行後にコマンドのインスタンスから取得した場合は、複数の値を返すようにすることもできます。

利点は、データアクセス層全体を複製として複製する必要がなく、それをサポートする単純なインフラストラクチャを作成している限り、コマンドを再利用して作成できることです。たとえば、他のコマンドからコマンドを実行します。

4
Euphoric

単純なシナリオでは、以下を使用しました。

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