创建ViewModels

时间:2015-08-12 16:12:25

标签: c# model-view-controller onion-architecture

也许你们中的一些人已经创建了基于洋葱架构的工作应用程序,并且已经处理了我的问题,并愿意分享他们的经验。

这是困扰我的。 让我们假设我有DomainModel" Customer"有100多列。 但是,对于特定视图,我只需要first and last name for rows meeting some specific conditions

我正在使用存储库/服务模式来公开一些基本的CRUD内容。 示例服务

    public class Service<TEntity, TKey> : IService<TEntity, TKey>
        where TEntity : BaseEntity<TKey>
        where TKey : IComparable
    {
        public IUnitOfWork UnitOfWork { get; private set; }
        private readonly IRepository<TEntity, TKey> _repository;
    }

public class CustomerService : Service<Customer,int>, ICustomerService
{
       public ???? GetValidCustomer();
}

现在我有三个想法如何处理它,但似乎没有一个好 1st)在控制器中编写查询

var viewModel = _customerRepository().GetAll().Where(...).Select(...).FirstOrDefault();

我不喜欢这个解决方案,因为它将业务逻辑引入控制器操作,这也可能创建可重复的代码。如果条件发生变化,我将不得不在整个项目中查找所有查询以进行更改。

2nd)将视图模型移动到Service layers
由于Web是洋葱架构中最外层并依赖于其他内层,因此我无法重用ViewModel并在Service layers中编写此类方法,因为不允许循环依赖

public ValidCustomerViewModel GetValidCustomer()
{
    return _customerRepository().Where(..).Select(new ValidCustomerViewModel() {....} ).FirstOrDefault();
}

同样在服务层创建ViewModel似乎并不适合它,因为我假设单一服务方法应该能够操作域而不是为视图创建数据(我认为这是{{1责任)

controller

3rd Creating Dto
创建public ValidCustomerViewModel GetValidCustomer() { var viewModel = new ValidCustomerViewModel(); viewModel.Customer _customerRepository().Where(..).Select(new ValidCustomerViewModel() {....} ).FirstOrDefault(); viewModel.Cats = _catRepository.Where(...).ToList(); } //So bad :( ViewModel和Dto

ont to one

这会产生一些额外的代码,但它可以修改,方法返回具体的属性。然而,这引入了新的问题...... 现在我可能需要编写类似

的方法
Inside -> (XXX.Web.Portal.ViewModels.Customer)
public class ValidCustomerViewModel()
{
   [Required]
   public string FirstName {get;set;}
   [Required]
   public string LastName {get;set;}
}

Inside ->(XXX.Core.Dto)
public class ValidCustomerDto
{
    public string FirstName {get;set;}
    public string LastName {get;set;}
}

public ValidCustomerDto GetValidCustomer()
{
    _customerRepository().Where(..).Project().To<ValidCustomerDto>().FirstOrDefault();
}

var dto = _customerServices().GetValidCustomers();
viewModel = Mapper.Map<ValidCustomerModel>(dto);

4rd返回IQueryable

public List<ValidCustomerDto> GetValidCustomers()
public PaginatedList<ValidCustomerDto>() GetPaginatedValidCustomersList(...)

当我写我的问题时,这个想法出现在我脑海里:) 嗯,这实际上并不坏,我认为没有重大缺陷。你觉得怎么样?

非常欢迎所有建议:)

1 个答案:

答案 0 :(得分:0)

我会选择第四个想法。

所以它会像:

服务层:

public class CustomerService
{
    public ValidCustomerDto GetValidCustomer()
    {
         _customerRepository.GetValidCustomer().Select(x=> new ValidCustomerDto{ FirstName = x.FirstName, LastName = x.LastName });
    }
}

作为另一种选择,您可以创建ReadOnly DbContext并直接使用它而不是仅用于查询的存储库,即命令和查询的分离(CQRS构思)。