EntityFramework подсчет результатов запроса в сравнении со списком подсчета

Должен 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
}

2 ответа

Просто столкнулся с этим сам. В моем случае проблема заключается в том, что в запросе есть предложение.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, которая возвращает все заказы, в то время как второй запрос представляет собой монстр из 100+ строк SQL, который имеет 10 внутренних объединений, которые инициируются. Предложение Select () (получено несколько связанных значений / агрегатов, чем показано здесь).

По сути, это указывает на то, что.Count() не учитывает предложение.Select() при подсчете, поэтому те же отношения, которые вызывают дальнейшее ограничение результирующего набора, не запускаются для.Count().

Я смог сделать эту работу, явно добавив выражения к методу.Count(), которые извлекают некоторые из этих агрегированных значений результатов, которые также эффективно вводят их в запрос.Count():

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

Ключ заключается в том, чтобы убедиться, что любое из полей, которые вычисляются или извлекают связанные данные и вызывают срабатывание отношения, включены в выражение, которое заставляет Count () включить требуемые отношения в свой запрос.

Я понимаю, что это полный взлом, и я надеюсь, что есть лучший способ, но на данный момент это позволило нам, по крайней мере, получить правильное значение, не используя сначала массивные данные с помощью.ToList().

Предполагая, что здесь efQuery является IQueryable:

ToList() на самом деле выполняет запрос. Если изменения в данных в хранилище данных, между вызовами ToList() а также .Count(), приведите к другому набору результатов, вызывая ToList() пополнит список. ToList().Count а также .Count() должен соответствовать, пока данные в хранилище не изменят набор результатов снова.

Другие вопросы по тегам