我刚开始使用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)
});
}
}
}
答案 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包。