在MVVM WPF中将实体框架数据库上下文(模型)连接到ViewModel的最佳方法是什么?


9

如上述问题:在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

Answers:


4

我已经研究了很多,还没有找到“完美”的解决方案。存储库模式对于上下文短暂的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);
}

这会将您的所有存储库归为一类,因此您不必处理单独的上下文。通过将方法分组到不同的文件中,它可以使您更好地管理不同的存储库,并有助于防止代码重复。最重要的是,您的上下文没有使用此模式就已经存在很短。

缺点是,对于较大的系统,您可能有很多方法绑定在您的存储库中。在这种情况下,一种解决方案是实施一些基本的通用命令,例如“查找”或“添加”,并在其各自的存储库中实施专门的命令。


2
您可以替换“ MyEntityRepository” EF自己的上下文,并且得到相同的结果。除非您想用自己的“存储库”包装EF的上下文,否则会增加重复。
欣快的

@Euphoric是的,可以,但是不能保证在上下文中使用存储库。重点是将EF的工作方式抽象化为简单的业务需求
Shoe

4

反对我不喜欢的存储库。我建议使用Ayende推荐的Command模式。

简而言之,您将为每个操作创建一个单独的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
您不应在类内部创建上下文的实例,而应将其注入构造函数中。
奥斯卡·梅德罗斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.