Trong trường hợp này, điều quan trọng là phải phân biệt giữa IQueryable<T>
và IEnumerable<T>
. Tóm lại IQueryable<T>
được xử lý bởi nhà cung cấp LINQ để cung cấp một truy vấn tối ưu. Trong quá trình chuyển đổi này, không phải tất cả các câu lệnh C # đều được hỗ trợ, vì không thể dịch chúng sang truy vấn cụ thể phía sau (ví dụ SQL) hoặc do người triển khai không thấy trước nhu cầu về câu lệnh.
Ngược lại IEnumerable<T>
được thực hiện chống lại các đối tượng cụ thể và, do đó, sẽ không được chuyển đổi. Vì vậy, điều khá phổ biến là các cấu trúc, IEnumerable<T>
có thể sử dụng được, không thể được sử dụng IQueryable<T>
và cũng được IQueryables<T>
hỗ trợ bởi các nhà cung cấp LINQ khác nhau không hỗ trợ cùng một bộ chức năng.
Tuy nhiên, có một số cách giải quyết (như câu trả lời của Phil ), điều chỉnh sửa truy vấn. Ngoài ra, như một cách tiếp cận tổng quát hơn, có thể quay trở lại IEnumerable<T>
trước khi tiếp tục với đặc tả của truy vấn. Tuy nhiên, điều này có thể có một điểm nhấn về hiệu suất - đặc biệt là khi sử dụng nó trong các hạn chế (ví dụ: các mệnh đề). Ngược lại, khi xử lý các phép biến đổi, hiệu năng đạt được nhỏ hơn rất nhiều, đôi khi thậm chí không tồn tại - tùy thuộc vào truy vấn của bạn.
Vì vậy, đoạn mã trên cũng có thể được viết lại như thế này:
return this.ObjectContext.BranchCostDetails
.AsEnumerable()
.Where(
b => b.TarrifId == tariffId && b.Diameter == diameter
|| (b.TarrifId==tariffId && !string.IsNullOrWhiteSpace(b.Diameter))
||(!b.TarrifId.HasValue) && b.Diameter==diameter
);
LƯU Ý: Mã Ths sẽ có tác động hiệu suất cao hơn câu trả lời của Phil . Tuy nhiên, nó cho thấy nguyên tắc.
List<string> my = new List<string>(); var i = from m in my where !string.IsNullOrWhiteSpace(m) select m;