MVVM在哪里放置数据访问层?

Dan*_*ack 28 c# design-patterns mvvm

我正在研究WPF的MVVM设计模式.但我不确定在哪里放置数据访问代码?

在我看过的一些例子中,数据访问是直接在ViewModel中执行的.在ViewModel中将linq这样的东西放到sql中似乎很奇怪?其他示例有一个单独的数据访问项目,这似乎更像?

这有一般方法吗?我觉得我在这里错过了一些东西!

谢谢

dev*_*xer 42

以下是我组织MVVM与LINQ项目的方式:

模型 - 我认为模型是系统的状态.它提供数据接口,并跟踪系统状态.模型不知道ViewModel或View - 它只是为其数据和各种事件提供一个公共接口,让消费者(通常是ViewModels)知道状态何时发生了变化.

ViewModel - ViewModel负责组织或构建View所需的所有数据,跟踪视图的状态(例如当前选定的数据网格行),并响应视图上的操作(例如按钮推动).它知道视图需要什么,但实际上并不了解视图.

视图 - 视图是UI的实际外观.它包含所有内置和自定义控件,它们的排列方式以及它们的样式.它知道ViewModel,但仅用于绑定其属性.

网关 - 这是直接解决您的问题的部分.网关(基本上我称之为"DataAccessLayer")是它自己的独立层.它包含CRUD的所有代码(包括LINQ查询),或者从/向数据源(数据库,XML文件等)选择,插入,更新和删除数据.它还为Model提供了一个公共接口,允许Model专注于维护系统状态,而不必关心更新数据源所需的细节(即查询).

DataAccess类 - 在C#中,这些是非常简单的类,用于为元素数据对象建模.当您使用LINQ查询选择某些内容时,通常会创建一个IEnumerable<T>List<T>哪个T是您的数据对象.数据对象的一个​​例子是:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这样设计的一大优势在于它真正区分了您的顾虑.一切都有专门的工作,而且(通常)很容易知道什么样的东西在哪里.

缺点是对于小型项目来说可能有点过分.您最终会为公共接口创建大量基础结构,这些基础结构基本上可以通过多个层传递单个愿望.所以,你可能会得到这样的场景:[用户点击提交,ViewModel告诉Model到AddNewPerson,Model告诉Gateway到InsertPerson]而不是像这样的场景[用户点击提交,ViewModel直接向数据库添加新记录].

希望有所帮助.

  • 你能不能提供一个你对mvvm的解释的简短例子,因为如果寻找好的DAL解决方案,我总是达到死胡同 (8认同)
  • 在网关中,您提到“它还为模型提供了一个公共接口”,如果该接口由模型决定/控制并由网关实现,以便在这些层之间实现控制反转,不是更好吗? (2认同)

Luk*_*asz 12

我会添加另一个层,基本上你想要的是一个数据工厂.您想要为您创建一组CRUD到数据库的类,并将干净的POCO对象返回到ViewModel.

一个很好的例子可以看看书呆子晚餐书.它涵盖了MVC而不是MVVM,但模式非常相似,它们在该解决方案中访问数据的方式将是一个很好的起点.

希望这可以帮助.

  • 谢谢.我喜欢Nerd Dinner使用Repository模式的方式(也是Kristoffer建议的).在文件结构方面,我想我会将Repository类和相关的映射器分离到Data Access目录.看起来好像它是MVVM中未提及的大面积区域.再次感谢. (2认同)

Kri*_*fer 11

数据访问应该在视图模型中,因为这应该是域模型的视图特定(可能简化)表示.

使用某种映射器将您的视图模型(MVVM中的VM)映射到您的模型(第一个M).可以使用工厂模式创建模型中的新对象.创建后,您可以使用存储库模式将它们存储在数据库中.然后,存储库将代表您的数据访问层.在您的存储库中,您可以使用像NHibernate或Entity Framework这样的O/R映射器.

编辑:
我看到GraemeF建议将数据访问代码放入模型中.这不是一个好方法,因为如果您要从SQL Server迁移到Oracle或XML文件,这将迫使您更新域模型.域对象不应该担心它们是如何持久化的.存储库模式将域与其持久性隔离开来.

  • 好点子; 当然,你还可以更进一步。我的观点是,数据访问代码隐藏在该界面后面,并且不存在于 ViewModel 中。 (2认同)

Gra*_*meF 7

MVVM代表Model,ViewViewModel.您缺少的部分是Model,它是您的数据访问代码所在的位置.

ViewModel接受Model并将其呈现给View进行显示,所以通常你会有这样的东西:

class PersonModel : IPerson
{
    // data access stuff goes in here
    public string Name { get; set; }
}

class PersonViewModel
{
    IPerson _person;

    public PersonViewModel(IPerson person)
    {
        _person = person;
    }

    public Name
    {
        get { return _person.Name; }
        set { _person.Name = value; }
    }
 }
Run Code Online (Sandbox Code Playgroud)

PersonView随后将绑定到的属性PersonViewModel,而不是直接到模型本身.在许多情况下,您可能已经拥有一个对MVVM一无所知的数据访问层(也不应该知道),但您仍然可以构建ViewModel以将其呈现给视图.

  • 选择这个。 (2认同)