2

linq 式のOrderBy句をリファクタリングできるようにしたいと考えています。

where句 のリファクタリングの例を次に示します。

前:

results = ctx.ActiveUsers
    .Where(u => u.CompanyID != 1 &&
           (u.LastName.ToLower().Contains(searchString)
           || u.Email.ToLower().Contains(searchString)
           || u.Company.Name.ToLower().Contains(searchString)))
    .OrderBy(u =>  u.LastName ).ThenBy(u => u.FirstName)
    .Select(u => new Employee {
      ID = u.ID
      , FirstName = u.FirstName
      , LastName = u.LastName
      , Email = u.Email
      , CompanyName = u.Company.Name
      , CompanyID = u.CompanyID.ToString() });

後:

results = ctx.ActiveUsers
    .Where(Employee.GetExpression(searchString))
    .OrderBy(u =>  u.LastName ).ThenBy(u => u.FirstName)
    .Select(u => new Employee {
      ID = u.ID
      , FirstName = u.FirstName
      , LastName = u.LastName
      , Email = u.Email
      , CompanyName = u.Company.Name
      , CompanyID = u.CompanyID.ToString() });

private static Expression<Func<User, bool>> GetExpression(string searchString)
{ 
    Expression<Func<User, bool>> p = (u => u.CompanyID != 1 &&
                       (u.LastName.ToLower().Contains(searchString)
                       || u.Email.ToLower().Contains(searchString)
                       || u.Company.Name.ToLower().Contains(searchString)));
    return p;
}

Orderby式をリファクタリングしたい以外は、同じタイプのことが可能かどうか疑問に思っていました。

前もって感謝します

4

3 に答える 3

3

「LastName」、「FirstName」などの文字列を実際に取得したい場合、次のようにします。

var unordered = ctx.ActiveUsers
                   .Where(Employee.GetExpression(searchString))
                   .OrderBy(ordering)
                   .Select(u => new Employee {
                       ID = u.ID,
                       FirstName = u.FirstName,
                       LastName = u.LastName,
                       Email = u.Email,
                       CompanyName = u.Company.Name,
                       CompanyID = u.CompanyID.ToString() });

新しい OrderBy 拡張メソッドを追加します。

public static class UserQueryableExtensions
{
    public static IOrderedQueryable<User> OrderBy(this IQueryable<User> source,
                                                  string ordering)
    {
        switch (ordering)
        {
            case "LastName":
                return source.OrderBy(x => x.LastName);
            case "FirstName":
                return source.OrderBy(x => x.FirstName);
            case "Email":
                return source.OrderBy(x => x.Email);
            case "Company":
                return source.OrderBy(x => x.Company);
            default:
                throw new ArgumentException("Unknown ordering");
        }
    }
}

確かにリフレクションを使用してこれを行うことができますが、重要なプロパティ セットがない限り (または、異なるエンティティ タイプに対して同じルーチンを使用したい場合)、switch ステートメントの方が簡単です。

于 2008-12-17T16:10:01.587 に答える
1

ジョン、ありがとう

その答えは、今のところ正しい道を歩んでいます...ただし、注文でThenBy句を保持する必要があります。したがって、以下のソリューションは動的ではありませんが、それでもThenByを保持します

var unordered = ctx.ActiveUsers
                   .Where(Employee.GetExpression(searchString))
                   .MyOrder()
                   .Select(u => new Employee {
                       ID = u.ID,
                       FirstName = u.FirstName,
                       LastName = u.LastName,
                       Email = u.Email,
                       CompanyName = u.Company.Name,
                       CompanyID = u.CompanyID.ToString() });

public static class UserQueryableExtensions
{
    public static IOrderedQueryable<User> MyOrder(this IQueryable<User> source )
    { 
        return source.OrderBy(x => x.LastName).ThenBy(x => x.FirstName).ThenBy(x => x.Email);
    }
}
于 2008-12-17T20:14:48.330 に答える
0

タイプミスなどを避けるために可能な限りラムダを使用することについてJonに同意します。ただし、(何らかの理由で)本当にこれができない場合はOrderBy、過去に完全に動的なものを見てきました。LINQ-to-SQL でテストされた例については、こちらを参照してください(ただし、理論上は EF で問題ないはずです)。

于 2008-12-17T19:46:55.797 に答える