0

簡単にするために、次の 2 つのクラスがあると仮定します。

public class ComplexClass
{
    public List<SubClass> SubClasses { get; set; }
    public string Name { get; set; }
}

public class SubClass
{
    public string Name { get; set; }
}

があり、List<ComplexClass>いくつかのパラメーターに基づいてクエリを作成する必要があります。

Nameのプロパティを使用するだけでよい場合は、簡単な作業ですComplexClass。次に例を示します。

    static IQueryable<ComplexClass> GetQuery(string someParameter, string someOtherParameter)
    {
        var query = list.AsQueryable();
        if (!String.IsNullOrEmpty(someParameter))
            query = query.Where(c => c.Name.StartsWith(someParameter));
        if (!String.IsNullOrEmpty(someOtherParameter))
            query = query.Where(c => c.Name.EndsWith(someOtherParameter));
        return query;
    }

私が持っているパラメーターに基づいて、さらにクエリ要素を追加できます。もちろん、上記の例は単純ですが、実際の問題にはさらに多くのパラメーターが含まれており、その数は増える可能性があります。

パラメータに基づく基準を満たすComplexClassインスタンスを持つインスタンスを見つけたい場合、物事はそれほど単純ではありません。SubClass

    static IQueryable<ComplexClass> GetSubQuery(string someParameter, string someOtherParameter)
    {
        var query = list.AsQueryable();
        if (!String.IsNullOrEmpty(someParameter))
            if (!String.IsNullOrEmpty(someOtherParameter))
                return query.Where(c => c.SubClasses.Where(sc => sc.Name.StartsWith(someParameter) && sc.Name.EndsWith(someOtherParameter)).Any());
            else
                return query.Where(c => c.SubClasses.Where(sc => sc.Name.StartsWith(someParameter)).Any());
        else
            if (!String.IsNullOrEmpty(someOtherParameter))
                return query.Where(c => c.SubClasses.Where(sc => sc.Name.EndsWith(someOtherParameter)).Any());
            else
                return null;
    }

各パラメーターに基づいてクエリのビットを追加するだけでは済みません。クエリ全体を一度に記述する必要があります。これは、パラメーターのすべての組み合わせをチェックする必要があることを意味しますが、これは理想的ではありません。

クラスを構築し、そこからラムダ式を作成することが重要Expressionだと思いますが、問題に取り組む方法がわかりません。

助言がありますか?:)

編集:

私の最初のアイデアはこれでした:

    static IQueryable<ComplexClass> GetSubQuery(string someParameter, string someOtherParameter)
    {
        var query = list.AsQueryable();
        query = query.Where(c =>
        {
            var subQuery = c.SubClasses.AsQueryable();
            if (!String.IsNullOrEmpty(someParameter))
                subQuery = subQuery.Where(sc => sc.Name.StartsWith(someParameter));
            if (!String.IsNullOrEmpty(someOtherParameter))
                subQuery = subQuery.Where(sc => sc.Name.EndsWith(someOtherParameter));
            return subQuery.Any();
        });
        return query;
    }

これは、LINQ to Objects を使用しているため、私の小さなコンソール テスト アプリケーションで機能します。残念ながら、Entity Framework と LINQ to Entities を使用する必要があるため、上記のような実装でA lambda expression with a statement body cannot be converted to an expression treeエラー メッセージがスローされます。

4

2 に答える 2

1

実際のコードでは、SubClassesプロパティは?IQueryable<SubClass>ではなくList<SubClass>

その場合、クエリの作成は簡単になります。

static IQueryable<ComplexClass> GetSubQuery(
    string someParameter, string someOtherParameter)
{
    var query = list.AsQueryable();
    if (!String.IsNullOrEmpty(someParameter))
        query = query.Where(c => c.SubClasses
            .Where(sc => sc.Name.StartsWith(someParameter)).Any());
    if (!String.IsNullOrEmpty(someOtherParameter))
        query = query.Where(c => c.SubClasses
            .Where(sc => sc.Name.StartsWith(someOtherParameter)).Any());
    return query;
}

混合IEnumerable<T>IQueryable<T>て使用するAsQueryable()ことは決して良い考えではありません。

于 2012-10-23T10:55:25.227 に答える
0

シンプルなコンソール プロジェクトにソリューションを実装しました。

internal class Program
{
    #region Constants and Fields

    private static readonly List<ComplexClass> list = new List<ComplexClass>
                                                          {
                                                              new ComplexClass
                                                                  {
                                                                      Name = "complex", 
                                                                      SubClasses = new List<SubClass>
                                                                                       {
                                                                                           new SubClass
                                                                                               {
                                                                                                   SubName = "foobar"
                                                                                               }
                                                                                       }
                                                                  }, 
                                                              new ComplexClass
                                                                  {
                                                                      Name = "complex", 
                                                                      SubClasses = new List<SubClass>
                                                                                       {
                                                                                           new SubClass
                                                                                               {
                                                                                                   SubName = "notfoobar"
                                                                                               }
                                                                                       }
                                                                  }
                                                          };

    #endregion

    #region Public Methods

    public static void Main(string[] args)
    {
        Console.WriteLine("foo / bar :");
        GetSubQuery("foo", "bar");
        Console.WriteLine();

        Console.WriteLine("foo / null :");
        GetSubQuery("foo", null);
        Console.WriteLine();

        Console.WriteLine("string.Empty / bar :");
        GetSubQuery(string.Empty, "bar");
        Console.WriteLine();

        Console.WriteLine("maeh / bar :");
        GetSubQuery("maeh", "bar");

        Console.ReadKey();
    }

    #endregion

    #region Methods

    private static void GetSubQuery(string startsWith, 
        string endsWith)
    {
        var query = from item in list
                    let StartIsNull = string.IsNullOrEmpty(startsWith)
                    let EndIsNull = string.IsNullOrEmpty(endsWith)
                    where
                        (StartIsNull || item.SubClasses.Any(sc => sc.SubName.StartsWith(startsWith)))
                        && (EndIsNull || item.SubClasses.Any(sc => sc.SubName.EndsWith(endsWith)))
                    select item;

        foreach (var complexClass in query)
        {
            Console.WriteLine(complexClass.SubClasses.First().SubName);
        }
    }

    #endregion

    public class ComplexClass
    {
        #region Public Properties

        public string Name { get; set; }
        public List<SubClass> SubClasses { get; set; }

        #endregion
    }

    public class SubClass
    {
        #region Public Properties

        public string SubName { get; set; }

        #endregion
    }
}

コンソール出力は次のとおりです。

foo / bar :
foobar

foo / null :
foobar

string.Empty / bar :
foobar
notfoobar

maeh / bar :
于 2012-10-23T11:19:44.070 に答える