2

Im using Linq to return IDs from 4 cascading dropdown menus.

The user may have selected 1 or more values from either 1 or all of the menus. From the users selections, Im then quering the text columns of a DataTable for the representative IDs.

If the user selects from the 4th (and lowest level) dropdown, then they would have selected from all those above.

If the user selects "X" from menu 1, "Y" from menu 2, and nothing in the others i would expect to see results1 with say 10 rows where "X" exists in [Col_1], which would then be queried down to say 5 rows in results2 where "Y" exists in [Col_2].

EDIT The Code (in a basic form)

var results1 = 
    from a in dt.AsEnumerable()
    where stringArray1.Contains([Col1])
    select a;


var results2 = 
    from a in results1
    where stringArray2.Contains([Col2])
    select a;

var results3 = 
    from a in results2
    where stringArray3.Contains([Col3])
    select a;

var results4 = 
    from a in results3
    where stringArray4.Contains([Col4])
    select a;

var results = results4 ?? results3 ?? results2 ?? results1;

results4 depends on the results from results3, results3 on results2, and results2 on results1.

It may be that results4 - 2 are empty , and therefore I was wondering if I could coalesce these into a final variable, eg:

var results = results4 ?? results3 ?? results2 ?? results1;

This is throwing the error:

Operator '??' cannot be applied to operands of type 'System.Collections.Generic.IEnumerable<AnonymousType#4>'

Does anyone have any cunning ideas how to resolve this? Im trying not to write very long winded code, handling every possible outcome.

Thank you all in advance (hopefully the question makes sense!)

CM

4

3 に答える 3

5

したがって、使用しているクエリに基づいて、結果はどれもnull. それらのいくつかは空かもしれませんが、そうではありませんnull。これは、??オペレーターが有用なことを何もしないことを意味します。

これをどのように動作させたいですか?「この結果が空の場合は、この別の結果を使用してください」と言いたいですか? そのためには、私が以下に書いた方法を使用してください。

public static IEnumerable<T> Coalesce<T>(IEnumerable<T> first, IEnumerable<T> second)
{
  if(first == null || !first.Any())
  {
    return second;
  }
  else
  {
    return first;
  }
}

これは次のように使用できます。

Coalesce(results4, Coalesce(results3, Coalesce(results2, results1)));

この結果は、「result4空でなければ return 。空のresults3場合は return 。空の場合results3は return results2、空の場合results2は return results1」です。

十分に使用できると思われる場合は、拡張メソッドにすることができます。それはよりきれいになりますが、他のすべての s の intellisense が乱雑になるIEnumerableため、価値がないかもしれません。

于 2012-05-30T15:06:53.403 に答える
0

事後に対処するのではなく、問題を解決するためにクエリを書き直します。

public List<string> FilterResults(string first, string second, string third, string fourth)
{
    var query = from a in dt.AsEnumerable()
                let firsts = first != null ? a.Where( x => x.stringArray1.Contains( first ) ) : null,
                let seconds = second != null ? firsts.Where( x => x.stringArray2.Contains( second ) ) : null,
                let thirds = third != null ? seconds.Where( x => x.stringArray3.Contains( third ) ) : null,
                let fourths = fourth != null ? thirds.Where( x => x.stringArray4.Contains( fourth ) ) : null
                select fourths ?? thirds ?? seconds ?? firsts;
    return query.ToList();
}

私はVSを通してこれを実行しませんでしたが、一般的な考えは出くわすはずです。

于 2012-05-30T16:13:10.990 に答える
0

長いコードを書きたくない場合は、次のことができます

public static IEnumerable<T> SomeOrAll<T>(
    this IEnumerable<T> source, 
    Predicate<T> where)
{
    var results = source.Where(where)
    return results.Any() ? results : source;
}

var results = dt.AsEnumerable()
    .SomeOrAll(a => a.stringArray4.Contains([Col4]))
    .SomeOrAll(a => a.stringArray3.Contains([Col3]))
    .SomeOrAll(a => a.stringArray2.Contains([Col2]))
    .SomeOrAll(a => a.stringArray1.Contains([Col1]));

しかし、少し後退すれば、何か他のことができるのではないかと思います。人々がこの拡張機能を頻繁に必要とする場合、それは既に存在しているでしょう (おそらく)。

于 2012-05-30T15:43:09.110 に答える