在N-Tier应用程序中使用DTO时的OrderBy
本文关键字:DTO 时的 OrderBy N-Tier 应用程序 | 更新日期: 2023-09-27 18:00:22
我有一个用C#-编写的分层应用程序
前端-(获取
Customers
的页面)业务-(
CustomerService
和Customer
类)数据合约-(
CustomerDTO
)数据访问-(
UnitOfWork
和Repositories
)
该数据库有一个Customer表,其中包含超过一百列(许多冗余列),因此我使用DTO在业务层填充Customer对象。在Customer类中,我也将许多字段的名称从数据库名称更改为,例如ID改为CustomerID,FName改为Firstname。
前端使用业务层的服务来获得客户,例如GetAll(), GetByID(int customerID).
我还想提供一个GetPaged method
如下。
客户服务等级
public IEnumerable<Customer> GetPaged(
Func<IQueryable<Customer>, IOrderedQueryable<Customer>> orderBy,
int skip,
int take)
{
foreach (var customerDTO in
unitOfWork.CustomerRepository.GetPaged(orderBy, skip, take))
{
yield return new Customer(customerDTO);
}
}
但这将不起作用,因为CustomerRepository
期望基于CustomerDTO
而不是Customer
的orderBy
。
我不想让前端知道任何关于CustomerDTO
的信息。
我怎样才能做到这一点?
您可以使用可用的订单选项公开enum
,然后在GetPaged
中,您只需根据收到的枚举值创建OrderBy。
可能的实施方式是:
public enum OrderCustomersBy
{
FirstNameAsc, FirstNameDesc, AgeAsc, AgeDesc
}
在客户服务中:
private IOrderedQueryable<CustomerDTO> GetOrderBy(OrderCustomersBy orderOption)
{
IOrderedQueryable<CustomerDTO> orderBy = null;
switch (orderOption)
{
case OrderCustomersBy.FirstNameAsc:
// Create order by...
break;
case OrderCustomersBy.FirstNameDesc:
// Create order by...
break;
case OrderCustomersBy.AgeAsc:
// Create order by...
break;
case OrderCustomersBy.AgeDesc:
// Create order by...
break;
default:
throw new NotImplementedException("Order option not implemented: " + orderOption.ToString());
}
return orderBy;
}
public IEnumerable<Customer> GetPaged(Func<IQueryable<Customer>> func, OrderCustomersBy orderOption, int skip, int take)
{
IOrderedQueryable<CustomerDTO> orderBy = this.GetOrderBy(orderOption);
foreach (var customerDTO in unitOfWork.CustomerRepository.GetPaged(orderBy, skip, take))
{
yield return new Customer(customerDTO);
}
}
我看到两个问题:第一,如何将业务实体映射到DTO;第二,如何在任何列上执行订单?
将业务实体映射到DTO。这可以通过多种方式实现。举几个例子:可以使用AutoMapper,你可以使用属性进行简单的映射(属性将包含customDTO或数据库列的属性名(使用数据库列可能会否定DTO的值)),也可以从数据库中驱动它,数据库方法有点重手和元。
我将按照评论中的建议使用动态顺序。是的,它确实增加了一层抽象,但减少了维护。
动态订单依据
public static IQueryable<T> OrderBy<T>(this IQueryable<T> items, string propertyName, SortDirection direction)
{
var typeOfT = typeof(T);
var parameter = Expression.Parameter(typeOfT, "parameter");
var propertyType = typeOfT.GetProperty(propertyName).PropertyType;
var propertyAccess = Expression.PropertyOrField(parameter, propertyName);
var orderExpression = Expression.Lambda(propertyAccess, parameter);
string orderbyMethod = (direction == SortDirection.Ascending ? "OrderBy" : "OrderByDescending");
var expression = Expression.Call(typeof(Queryable), orderbyMethod, new[] { typeOfT, propertyType }, items.Expression, Expression.Quote(orderExpression));
return items.Provider.CreateQuery<T>(expression);
}
在一天结束时,当我更改实体时,我对在应用程序的其他位置更改代码不感兴趣。