2011-08-06 8 views
95

私はこのクエリを持っている場合:最大の戻り値は空の​​問い合わせ

int maxShoeSize=Workers.Where(x=>x.CompanyId==8).Max(x=>x.ShoeSize); 

会社8は、まったくの労働者を持っていない場合maxShoeSizeになりますか?

UPDATE:
は、どのように私は0ではなく例外を取得するためにクエリを変更できますか?

+0

Naor :LINQPadについて聞いたことがありますか? –

+2

投票を行った人 - 理由を説明してください。 – Naor

+5

私のdownvoteではありませんが、おそらくあなた自身で容易に確かめることができたからです。 –

答えて

165
int maxShoeSize = Workers.Where(x => x.CompanyId == 8) 
         .Select(x => x.ShoeSize) 
         .DefaultIfEmpty(0) 
         .Max(); 

DefaultIfEmptyにおけるゼロは不要です。

3

マックスはSystem.InvalidOperationExceptionがスローされますWorkersは、Entity FrameworkのあなたからDbSetObjectSetある場合

を(ShoeSizeがタイプintであると仮定して)

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<MyClass> list = new List<MyClass>(); 

     list.Add(new MyClass() { Value = 2 }); 

     IEnumerable<MyClass> iterator = list.Where(x => x.Value == 3); // empty iterator. 

     int max = iterator.Max(x => x.Value); // throws System.InvalidOperationException 
    } 
} 

class MyClass 
{ 
    public int Value; 
} 
1
int maxShoeSize=Workers.Where(x=>x.CompanyId==8) 
    .Max(x=>(int?)x.ShoeSize).GetValueOrDefault(); 

を "シーケンスに要素が含まれていません"最初のクエリはInvalidOperationExceptionをスローしますが、空のシーケンスについては不満はしませんが、実体化された値NULLを変換できないと不平を言いますo int

15
int maxShoeSize = Workers.Where(x => x.CompanyId == 8) 
        .Select(x => x.ShoeSize) 
        .DefaultIfEmpty() 
        .Max(); 
1

NB:DefaultIfEmpty()でのクエリは、かなり遅いである可能性があります。 私の場合、これは.DefaultIfEmpty(DateTime.Now.Date)という単純なクエリでした。

私はプロファイルに怠惰でした。しかし、明らかに、EFはすべての行を取得してからMax()値を取得しようとしました。

結論:時々の取り扱いInvalidOperationExceptionが良い選択かもしれません。

28

私はこれが古い質問であり、受け入れられた答えが働いていることを知っていますが、この質問はそのような空のセットが例外またはdefault(int)という結果になるかどうかについて私の質問に答えました。

しかし、それはうまくいっていますが、理想的な解IMHOではありません。ここでは説明しません。したがって、私はそれを探している人の利益のために私自身の答えでそれを提供しています。

OPの元のコードをした

int maxShoeSize = Workers.Where(x => x.CompanyId == 8).Max(x => x.ShoeSize); 

これは私が例外を防ぎ、デフォルトの結果を提供するために、それを書くだろうかです:

int maxShoeSize = Workers.Where(x => x.CompanyId == 8).Max(x => x.ShoeSize as int?) ?? 0; 

これはにMax機能の戻り値の型を引き起こしnullの結果が得られるint?となり、nullの結果が0に置き換えられます。次に、??0の結果に置き換えられます。

+1

すばらしい解決策! 'DefaultIfEmpty'のより一般的な答えは、' Max'が評価をしていないときだけうまく動作します。 – McGuireV10

+0

@ McGuireV10ええ、私は通常、結果に 'Max'のような集計関数を使うつもりなら、中間の人間として' Select'を使うのは好きではありません。私は_think_(私はまだこれをテストしていません)は、生成されたSQLは、それを行うことによって余分な副選択クエリを使用するのに対し、私はnullを返すことによって空のセットを処理することになります。 upvoteとフィードバックをありがとう! ;) – CptRobby

+0

@ McGuireV10同様に、 'ShoeSize'が実際に関連する' Uniform'エンティティにある場合、私は 'Workers.Where(x => x.CompanyId == 8)を使用しません.Select(x => x.Uniform ).Max(x => x。'Workers.Where(x => x.CompanyId == 8).Max(x => x.Uniform.ShoeSize) 'と評価してください。私はクエリを効率的に構築する方法を決定する際にEFが最大の自由度を持つことを可能にするために、クエリでできるだけ少ないメソッドを使用することを好みます。 ;-) – CptRobby

0

.Max()内の3進数を使用して述語を処理し、その値を設定することができます。

// assumes Workers != null && Workers.Count() > 0 
int maxShoeSize = Workers.Max(x => (x.CompanyId == 8) ? x.ShoeSize : 0); 

ことが可能だ場合は、空/ nullであることWorkersコレクションを処理する必要があるでしょうが、それはあなたの実装に依存することになります。

0

あなたはこれを試すことができます:マックスを行う前に、すべての労働者は()がある場合

int maxShoeSize = Workers.Where(x=>x.CompanyId == 8).Max(x => x.ShoeSize) ?? 0; 
0

あなたはチェックすることができます。

private int FindMaxShoeSize(IList<MyClass> workers) { 
    var workersInCompany = workers.Where(x => x.CompanyId == 8); 
    if(!workersInCompany.Any()) { return 0; } 
    return workersInCompany.Max(x => x.ShoeSize); 
} 
0

これがLinq to SQLの場合は、SQLサーバーへの複数のクエリが発生するため、Any()を使用したくありません。 ShoeSizeがNULL可能フィールドでない場合は、単に.Max(..) ?? 0を使用して動作しません

が、次のようになります。

int maxShoeSize = Workers.Where(x = >x.CompanyId == 8).Max(x => (int?)x.ShoeSize) ?? 0; 

それは絶対に放出されたSQLを変更しませんが、シーケンスがある場合には0を返すんそれはMax()がintを返すように変更するので空ですか? intの代わりに。

関連する問題