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


9

上記の質問のように: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に適応できるかどうかわかりません

回答:


4

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

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

  1. EDMXがデータアクセスレイヤーとして機能する別のプロジェクトを作成する
  2. 同じプロジェクトの下に「リポジトリ」フォルダを作成します
  3. 「作業ユニット」として機能する基本クラス「BaseRepository」を作成します。IDisposableあなたがAでこれを使用できるようになります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つの解決策は、「検索」や「追加」などのいくつかの基本的な一般的なコマンドを実装し、それぞれのリポジトリに専用のコマンドを実装することです。


2
「MyEntityRepository」EF自体のコンテキストを置き換えることができ、同じ結果が得られます。EFのコンテキストを独自の「リポジトリ」でラップしたくない場合を除き、複製を増やします。
陶酔した

@Euphoric可能ですが、リポジトリがコンテキスト上で使用されることは保証されません。重要なのは、EFが単純なビジネス要件に取り組む方法を抽象化することです
Shoe

4

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

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

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

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


0

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

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

}

1
これの問題は、あなたのコンテキストが潜在的に「長生き」することです。
2013年

1
クラス内にコンテキストのインスタンスを作成するのではなく、代わりにコンストラクタにそれを注入する必要があります。
オスカーメデロス2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.