MVC2混淆何时使用viewmodels或域对象

时间:2011-06-22 13:28:07

标签: asp.net-mvc-2 repository viewmodel

继教程之后是Steve Sandersons专业的asp.net框架书籍我已经设法使用存储库模式获得两个数据库对象的基本编辑和显示功能。

当我想要显示/更新多个对象的属性时,我遇到了问题。

我知道viewmodels是一种做到这一点的方法,但我很困惑何时应该使用viewmodel以及它们如何适应我的域模型对象。

例如,对于我的两个对象,我有存储库和以下方法来返回每个对象列表

public IQueryable<Customer> Customers
    {
        get { return customersTable; }
    } 

public IQueryable<CustomerSite> CustomerSites
    {
        get { return customerSitesTable; }
    }

然后在我的控制器中将对象从存储库传递到视图,如

 public ViewResult List([DefaultValue(1)] int page)
    {
        var customerSitesToShow = customerSiteRepository.CustomerSites;
        var customersToShow = customerRepository.Customers; 
        var viewModel = new CustomerSitesListViewModel
        {

            CustomerSites = customerSitesToShow.Skip((page - 1) *  PageSize).Take(PageSize).ToList(),
            customers = customersToShow.Skip((page - 1) * PageSize).Take(PageSize).ToList(),

            PagingInfo = new PagingInfo
            {
                CurrentPage = page,
                ItemsPerPage = PageSize,
                TotalItems = customerSitesToShow.Count()
            }
        };

        return View(viewModel);  //Passed to view as ViewData.Model (or simply model)
    }

}

我现在明白我可以使用viewmodel来访问一个视图中两个对象的属性,所以我有一个viewmodel,其中包含两个对象的属性

{
public class SiteViewModel
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
    public string AddressLine1 { get; set; }
}

public class CustomerViewModel
{
    public int Id { get; set; }
    public string CustomerName { get; set; }
    public string PrimaryContactName { get; set; }
    public SiteViewModel Site { get; set; }
}

}

然后是我强烈键入显示模板的主视图模型

public class CustomerSitesListViewModel
{
    public IList<CustomerSite> CustomerSites { get; set; }
    public PagingInfo PagingInfo { get; set; }
    public IList<Customer> customers { get; set; }
    public CustomerViewModel Customers { get; set; }
}

当我运行这个时,显示模板被渲染,但我的客户集合是空的,因为我认为我需要一个LINQ join语句来检索客户列表和客户站点? LINQ加入是最好的方法吗?所以我可以从显示模板中访问两个对象,如

<%= Html.DisplayFor(x => x.Customers.CustomerName) %>
<%= Html.DisplayFor(x => x.Customers.Site.AddressLine1) %>

这是我更加困惑的地方,如果在存储库或视图模型中,包含LINQ查询以返回客户集合的方法应该在哪里?

1 个答案:

答案 0 :(得分:0)

根据我的理解,你会混淆域对象和视图模型之间的两个不同职责。

我的模型看不太清楚。客户是否有一个或多个站点?他们之间的关系是什么?从我的角度来看,您可以在存储库级别执行什么操作,在该级别执行此操作。所以我会直接从存储库返回一个带有它的Site的客户,因为你可以在存储库级别使用连接聚合数据并将其返回到数据库中。

为什么要回到两个单独的实体Customer和CustomerSite,因为您知道在视图中需要它们?你需要创造更多的问题。

因此,可以在映射到平面视图模型对象(例如名为CustomerWithSite)之后立即从存储库中返回Customer和Site。为此,您可以使用AutoMapper(http://automapper.codeplex.com/)。您还可以为视图提供一个“特殊”存储库,这些视图已经返回了为视图格式化的对象,该视图是存储库中的查询和预测的问题。由你决定。但不要将您的域对象用于视图目的。

我也不会在我的存储库外面公开IQueryable。你会遇到麻烦。因为一旦您启用其他层来操作查询,存储库就不再对返回的内容负责。然后一些开发人员会尝试在视图中操作Iqueryable,但缺点是它需要打开数据库的连接。从我的观点来看,设置不是很好,以保持连接的开放性。如果之前连接关闭怎么办?在视图上显示对象时,您将获得Disposed异常。不是很好。还要考虑可测试性。

我不知道你是否更清楚,但要注意我所说的缺点。