3

我有一个用 C# 编写的分层应用程序 -

前端 - (获取页面Customers

商务 - (CustomerServiceCustomer班级)

数据合同 - ( CustomerDTO)

数据访问 - (UnitOfWorkRepositories)

数据库有一个包含一百多列(很多是冗余的)的 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期望orderBy基于CustomerDTOnot the Customer

我不想让前端知道任何关于CustomerDTO.

我怎样才能做到这一点?

4

2 回答 2

0

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);
    }
}
于 2013-03-05T17:35:26.643 回答
0

我看到两个问题:首先,您如何将业务实体映射到 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);
    }

一天结束时,当我更改实体时,我对更改应用程序中其他位置的代码不感兴趣。

于 2013-03-05T18:03:40.257 回答