也许你们中的一些人已经创建了基于洋葱架构的工作应用程序,并且已经处理了我的问题,并愿意分享他们的经验。
这是困扰我的。
让我们假设我有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(...)
当我写我的问题时,这个想法出现在我脑海里:) 嗯,这实际上并不坏,我认为没有重大缺陷。你觉得怎么样?
非常欢迎所有建议:)
答案 0 :(得分:0)
我会选择第四个想法。
所以它会像:
服务层:
public class CustomerService
{
public ValidCustomerDto GetValidCustomer()
{
_customerRepository.GetValidCustomer().Select(x=> new ValidCustomerDto{ FirstName = x.FirstName, LastName = x.LastName });
}
}
作为另一种选择,您可以创建ReadOnly DbContext并直接使用它而不是仅用于查询的存储库,即命令和查询的分离(CQRS构思)。