3

私はC#で書かれた階層型アプリを持っています-

フロントエンド-(のページを取得Customers

ビジネス-(CustomerServiceおよびCustomerクラス)

DataContracts-(CustomerDTO

DataAccess-(UnitOfWorkおよびRepositories

データベースには100を超える列(多くは冗長)を持つCustomerテーブルがあるため、DTOを使用してビジネスレイヤーでCustomerオブジェクトにデータを入力しています。Customerクラスでは、多くのフィールドの名前もデータベース名から変更しました。たとえば、IDをCustomerIDに、FNameをFirstnameに変更しました。

フロントエンドは、ビジネスレイヤーのサービスを使用して、顧客を獲得します。GetAll(), GetByID(int customerID).

私も以下のようなものを提供したいと思いGetPaged methodます。

CustomerServiceクラス

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期待しているため、これは機能しません。orderByCustomerDTOCustomer

フロントエンドにについて何も知られたくないCustomerDTO

どうすればこれを達成できますか?

4

2 に答える 2

0

enum利用可能な注文オプションを公開してGetPagedから、受け取った列挙値に基づいて OrderBy を作成するだけです。

可能な実装は次のとおりです。

public enum OrderCustomersBy
{
    FirstNameAsc, FirstNameDesc, AgeAsc, AgeDesc
}

そして CustomerService では:

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

2 つの問題があります。1 つ目は、ビジネス エンティティを DTO にマップする方法です。2 つ目は、任意の列で order-by を実行する方法です。

ビジネス エンティティを 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 に答える