使用ViewModels设计MVC存储库

Dr.*_*ite 7 model-view-controller asp.net-mvc repository viewmodel

我想创建一个存储库类来将我的数据逻辑与控制器分开.我使用ViewModel来表示将填充来自不同表的数据的一些数据.

以下是我的一些问题:

  1. 对于像GetAll()这样的方法,我会返回一个IQueryable<MyViewModel>IQueryable<Entity>?如果我返回视图模型,我该如何应对GetAll()拉动数千条记录?
  2. 我是否为自定义ViewModel类创建构造函数,该类将实体作为参数来进行映射?(我仍然不熟悉automapper,所以只需要从设计的角度理解如何做到这一点)

同样,我主要担心的是一种GetAll()可以提取许多记录的方法.如果我做了一个foreach循环来将每个实体转换为一个ViewModel似乎需要很多开销.我的想法是将自定义ViewModel类中的引用放入IQueryable<Entity>要从集合访问的内容,并让ListViewModel只有索引器或类似引用集合属性的引用.

Dar*_*rov 5

1)对于像GetAll()这样的方法,我是否返回IQueryable或IQueryable?如果我返回viewmodels,我该如何处理一个可以提取数千条记录的GetAll()?

IQueryable<Entity>.存储库不处理视图模型.可以将存储库视为在单独的类库中定义的内容,该库不引用您的视图模型所在的ASP.NET MVC应用程序.ASP.NET MVC应用程序引用此库.

2)我是否为自定义ViewModel类创建一个构造函数,该类将Entity作为参数来进行映射?(我仍然不熟悉automapper,所以只需要从设计的角度理解如何做到这一点)

不.不要在视图模型中创建构造函数,尤其是当您希望控制器操作将这些视图模型作为操作参数时(考虑POST操作).原因是默认模型绑定器将不再知道如何实例化视图模型,您将不得不编写自定义模型绑定器.

所以AutoMapper或手动映射.

您可以从手册映射开始的示例:

public ActionResult SomeAction()
{
    IEnumerable<Entity> entities = Repository.GetAll();
    IEnumerable<MyViewModel> model = entities.Select(x => new MyViewModel
    {
        Prop1 = x.Prop1,
        Prop2 = x.Prop2,
        ...
    }); 
    return View(model);
}
Run Code Online (Sandbox Code Playgroud)

一旦你厌倦了编写这个代码,就转移到AutoMapper:

public ActionResult SomeAction()
{
    IEnumerable<Entity> entities = Repository.GetAll();
    IEnumerable<MyViewModel> model = Mapper.Map<IEnumerable<Entity>, IEnumerable<MyViewModel>>(entities); 
    return View(model);
}
Run Code Online (Sandbox Code Playgroud)

或者,如果您编写自定义操作过滤器,使用OnActionExecuted事件来拉取传递给视图的域模型,使用AutoMapper将其映射到视图模型,并将模型替换为视图的视图模型,则可以进一步简化重复代码:

[AutoMap(typeof(IEnumerable<Entity>), typeof(IEnumerable<MyViewModel>))]
public ActionResult SomeAction()
{
    IEnumerable<Entity> entities = Repository.GetAll();
    return View(entities);
}
Run Code Online (Sandbox Code Playgroud)

同样,我主要担心的是像GetAll()这样的方法会拉出很多记录.如果我做了一个foreach循环来将每个实体转换为一个ViewModel似乎需要很多开销.

不要担心.拉取记录将比循环和映射到视图模型慢一些.