8

同じ値を生成する必要がefQuery.ToList().Countありますか?efQuery.Count()

同じ値を生成しない可能性はefQuery.ToList().Countありますか?efQuery.Count()

//GetQuery() returns a default IDbSet which is used in EntityFramework

using (var ds = _provider.DataSource())
{
    //return GetQuery(ds, filters).Count(); //returns 0???
    return GetQuery(ds, filters).ToList().Count; //returns 605 which is correct based on filters
}

4

2 に答える 2

6

自分でこれに遭遇しました。私の場合、問題は、クエリに .Select() 句が含まれていることです。これにより、さらに関係が確立され、関係の内部結合が結果を制約するため、クエリがさらにフィルタリングされます。

.Count() は、クエリの .Select() 部分を処理していないようです。

ので、私は持っています:

// projection created
var ordersData = orders.Select( ord => new OrderData() {
           OrderId = ord.OrderId,
           ... more simple 1 - 1 order maps

           // Related values that cause relations in SQL
           TotalItemsCost = ord.OrderLines.Sum(lin => lin.Qty*lin.Price),
           CustomerName = ord.Customer.Name,
};


var count = ordersData.Count();    // 207
var count = ordersData.ToList().Count // 192

SQL ステートメントを比較すると、Count() は Orders テーブルで非常に単純な SUM を実行し、すべての注文を返しますが、2 番目のクエリは . Select() 句 (ここに示されている以外にも、いくつかの関連する値/集計が取得されます)。

基本的に、これは .Count() がカウントを行うときに .Select() 句を考慮に入れていないことを示しているように思われるため、結果セットをさらに制約する原因となる同じ関係は .Count() に対して発生しません。

.Count() メソッドに式を明示的に追加することで、これを機能させることができました。これにより、集約された結果値の一部を取得し、それらを .Count() クエリにも効果的に強制します。

var count = ordersData.Count( o=> o.TotalItemsCost != -999 &&
                                  o.Customer.Name != "!@#");    // 207

重要なのは、計算された、または関連データを取り込んでリレーションシップを発生させるフィールドのいずれかが、Count() に必要なリレーションシップをクエリに含めることを強制する式に含まれていることを確認することです。

私はこれが完全なハックであることを認識しており、より良い方法があることを望んでいますが、現時点では、最初に .ToList() を使用して大量のデータを取得することなく、少なくとも適切な値を取得することができました。

于 2013-09-26T04:45:20.550 に答える