2013-07-03 24 views
7

Nếu efQuery.ToList().CountefQuery.Count() có cùng giá trị không? EntityFramework đếm kết quả truy vấn so với danh sách đếm

Làm cách nào để có thể efQuery.ToList().CountefQuery.Count() không tạo ra cùng một giá trị?

//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 
} 

+1

efQuery có thể đếm được hoặc có thể truy xuất được không? Ngoài ra, nếu bạn có thể đăng mã thực sự của mình để có thể trợ giúp. – Maess

+0

efQuery là 'IQueryable', nó là một truy vấn chưa được thực thi đối với cơ sở dữ liệu. Tôi đã thêm mã. – ReFocus

Trả lời

1

Giả sử ở đây là efQueryIQueryable:

ToList() thực sự thực hiện một truy vấn. Nếu thay đổi dữ liệu trong kho dữ liệu, giữa các cuộc gọi đến ToList().Count(), dẫn đến kết quả khác, gọi ToList() sẽ lặp lại danh sách. ToList().Count.Count() sau đó sẽ khớp cho đến khi dữ liệu trong cửa hàng thay đổi resultset một lần nữa.

+1

Dữ liệu không thay đổi giữa các cuộc gọi. Tôi có thể tái tạo vấn đề này mỗi khi tôi chạy mã. Cả hai cuộc gọi đều tạo ra các kết quả khác nhau. Ngay cả Resharper nói với tôi rằng tôi nên sử dụng phương thức '.Count()' thay vì buộc '.ToList()' và sử dụng thuộc tính '.Count' ... – ReFocus

+1

Count() trả về 0 vì danh sách chưa được điền . Bạn phải thực hiện truy vấn với ToList() trước khi truy vấn được thực thi. Nếu bạn thêm a.Đếm() (không có ToList()) sau dòng ToList(), số đếm sẽ chính xác. –

+2

Không, 'Đếm()' nên bắt buộc truy vấn trên 'IQueryable' - http://stackoverflow.com/questions/890381/how-to-count-rows-within-entityframework-without-loading-contents – ReFocus

5

Chỉ cần tự mình điều hành. Trong trường hợp của tôi, vấn đề là truy vấn có một mệnh đề .Select() gây ra các mối quan hệ khác được thiết lập mà cuối cùng sẽ lọc truy vấn thêm khi mối quan hệ bên trong kết nối hạn chế kết quả.

Dường như .Count() không xử lý phần .Select() của truy vấn.

Vì vậy, tôi có:

// 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 

Khi tôi so sánh các câu lệnh SQL Tôi tìm Đếm rằng() thực hiện một SUM rất đơn giản trên bảng Orders mà trả về tất cả các đơn đặt hàng, trong khi truy vấn thứ hai là một con quái vật của 100 + Các dòng của SQL có 10 kết nối bên trong được kích hoạt bởi mệnh đề .Select() (có thêm một vài giá trị liên quan/tập hợp được lấy ra được hiển thị ở đây). Về cơ bản, điều này dường như chỉ ra rằng .Count() không nhận mệnh đề .Select() khi nó đếm, vì vậy những mối quan hệ tương tự gây ra sự ràng buộc hơn nữa của tập kết quả không được kích hoạt cho .Count().

Tôi đã có thể làm cho công việc này bằng cách thêm một cách rõ ràng biểu cho phương thức Count() mà kéo trong một số những giá trị kết quả tổng hợp mà hiệu quả buộc họ vào Count() truy vấn cũng như:

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

Điều quan trọng là đảm bảo rằng bất kỳ trường nào được tính toán hoặc kéo dữ liệu liên quan và gây ra mối quan hệ với lửa, được bao gồm trong biểu thức buộc Count() bao gồm các mối quan hệ được yêu cầu trong truy vấn của nó.

Tôi nhận ra đây là một tổng số hack và tôi hy vọng có một cách tốt hơn, nhưng hiện tại điều này đã cho phép chúng tôi ít nhất để có được giá trị đúng mà không cần kéo dữ liệu lớn xuống .ToList() trước.

Các vấn đề liên quan