视图和域模型,在何处执行计算

时间:2012-04-03 07:00:55

标签: asp.net-mvc-3 domain-driven-design

我刚开始使用View&我的MVC Web应用程序中的域模型设计,但得到了执行计算和其他View相关操作的问题。我将尝试在下面举例。

我的域模型(Linq2Sql)

public class Product
{
  public int Id;
  public string Name;
}

我希望计算具有新UserCount属性的视图模型。

public class ProductViewModel
{
  public int Id;
  public string Name;
  public int UserCount;
}

我的控制器操作类似于

public ActionResult _SelectionClientSide_Products()
{
  IQueryable<Product> products = _repository.GetProducts(true); 
  var  model = Mapper.Map<IEnumerable<Product>, IEnumerable<ProductViewModel>>(products);                                
  return View(model);
}

我使用存储库方法查询数据并获取IQueryable<Product>并将其映射到ProductViewModel列表。但我还需要执行另一个查询操作来为每个查询的产品计算用户数,并将所有值分配给ProductViewModel。我应该遵循什么样的设计来实现这个目标?

表之间的关系

Products -> Orders - > Users

修改

我决定删除AutoMapper,因为它提供的问题多于好处,并创建了我自己的Builder,其中包含我需要的所有内容。我进行字段分配并添加计算。

    public ActionResult _SelectionClientSide_Products()
    {        
      Data = new ProductViewModelBuilder(_repository).Build();
      return View(Data);
    }

namespace PC.Models
{
            public class ProductViewModel
            {
                public int Id { get; set; }
                public string Name { get; set; }
                public int UsersCount { get; set; }
            }

            public class ProductViewModelBuilder
             {
                 private readonly IDataAccess _repository;

                 public ProductViewModelBuilder(IDataAccess repository)
                 {
                     _repository = repository;
                 }

                 public IQueryable<ProductViewModel> Build()
                 {
                     return _repository.GetProducts().Select(p=> new ProductViewModel
                                                                         {
                                                                             Id = p.Id, 
                                                                             Name = p.Name,
                                                                             UsersCount = _repository.CountUsers(p.Id)
                                                                         });         
                 }

            }
        }

1 个答案:

答案 0 :(得分:0)

在我看来,当你的控制器开始它的模型设置时,应该没有更多的“逻辑”或与模型交谈。拥有一个再次查询模型的“构建器”是不好的做法。并没有真正“打破”MVC模式,但仍然是不好的做法。您的ViewModel依赖于您的DAL。坏孩子。 :)

如果你必须运行另一个查询,那么应该封装在原始查询中。而不是调用_repository.GetProducts,而是调用另一种方法,不仅可以获取产品,还可以获得计数。如有必要,请创建DTO。

然后你的控制器应该是这样的:

public ActionResult _SelectionClientSide_Products()
{
  var someDto = _repository.GetProductsAndUserCount(true); 
  var  model = Mapper.Map<IEnumerable<SomeDto>, IEnumerable<ProductViewModel>>(someDto);                                
  return View(model);
}

我个人认为通用存储库超过了专用存储库,因为我不想要一个带有50个签名的IProductRepository接口。我选择LINQ IEnumerable<T>扩展(又名“管道和过滤器”),它允许构建复杂的查询并保留在我的域中。

所以我的上述版本将是:

public ActionResult _SelectionClientSide_Products()
{
  var someDto = _productRepository.Find().WithSomeCondition(true).ToSomeDto(); 
  var  model = Mapper.Map<IEnumerable<SomeDto>, IEnumerable<ProductViewModel>>(someDto);                                
  return View(model);
}

另外,为什么你说AutoMapper会给你带来更多有益的问题? AutoMapper为我节省了大量重复的代码。如果你知道如何正确使用它,它就是你最好的朋友。在我当前的应用程序中放下最重要的NuGet包。