2010-08-19 26 views
6

Tôi muốn trả về một tập hợp các thực thể có ID và được chứa trong danh sách hoặc mảng ID sử dụng LINQ và Dịch vụ dữ liệu. Tôi biết làm thế nào để điều này bằng cách sử dụng LinqToEF nhưng tôi đang ở một mất mát như thế nào với điều này với dịch vụ dữ liệu hoặc sử dụng các quy ước truy vấn OData cho rằng vấn đề.Chọn đối tượng trong đó ID trong mảng int - WCF Data Services, LINQ

suy nghĩ của tôi là tôi sẽ làm một cái gì đó như:

int[] intArray = {321456, 321355, 218994, 189232}; 
var query = (from data in context.Entity 
      where intArray.contains(data.ID) 
      select data); 

Có cách nào để thực hiện sử dụng dịch vụ dữ liệu/OData? Tôi biết tôi có lẽ có thể hack nó với một hoạt động dịch vụ nhưng tôi không muốn làm điều đó.

Chúc mừng.

Trả lời

8

Hiện tại OData (giao thức cơ bản) không hỗ trợ hoạt động Chứa. Vì vậy, đó là lý do tại sao thư viện khách hàng không dịch truy vấn trên. Con người về cơ bản đang sử dụng hai cách để vượt qua giới hạn này: 1) Sử dụng các thao tác dịch vụ như bạn đã lưu ý. 2) Xây dựng mệnh đề where động sử dụng phép so sánh đơn giản để so sánh giá trị với từng mục từ mảng. Vì vậy, nếu mảng chứa 1, 2, 3, nơi sẽ là data.ID == 1 || data.ID == 2 || data.ID == 3 Giải pháp # 2 là tốt bởi vì đó là một mặt khách hàng chỉ thay đổi. Nhược điểm là, nó chỉ hoạt động cho các mảng nhỏ. Nếu mảng chứa quá nhiều mục thì biểu thức quá dài và dẫn đến tất cả các loại phiền hà. Giải pháp # 1 không có vấn đề về kích thước, nhưng bạn cần cung cấp thao tác trên máy chủ.

+0

"Xây dựng mệnh đề where động sử dụng so sánh đơn giản để so sánh giá trị cho mỗi mục từ mảng "- bạn có thể cung cấp một ví dụ hay không. –

+0

Ví dụ sẽ khá dài - có thể bạn có thể tìm kiếm "LINQ động" và như vậy. Cách cấp thấp là sử dụng lớp Expression và API của nó để xây dựng truy vấn LINQ theo chương trình. –

0

Cảm ơn những người đàn ông bạn thực sự đã giúp tôi :) :)

Tôi đã làm như Vitek Karas nói.

1) Tải động truy vấn thư viện Kiểm tra này link

Không cần phải đọc nó chỉ cần tải các thư viện truy vấn động

2) Kiểm tra dự án đặt tên DynamicQuery. Trong đó bạn sẽ tìm thấy một lớp có tên là Dynamic.cs. Sao chép nó vào dự án của bạn

3) Tạo dự án của bạn (Nếu bạn đang sử dụng Silverlight thì có lỗi nói rằng ReaderWriterLock không được tìm thấy sẽ xuất hiện. Đừng sợ hãi. Chỉ cần bình luận hoặc xóa các dòng sai sót (chỉ có 6 hoặc 7 dòng mà làm lỗi))

4) Tất cả được thực hiện bạn chỉ cần bây giờ để viết truy vấn của bạn Ví dụ: ordersContext.CLIENTS.Where(" NUMCLI > 200 || NUMCLI < 20");

Tất cả được thực hiện. Nếu bạn phải sử dụng phương thức 'Chứa', bạn chỉ cần viết một phương thức lặp qua mảng của bạn và trả về chuỗi mà yêu cầu của bạn sẽ sử dụng.

private string MyFilter() 
{ string st = ""; 

     foreach(var element in myTab) 
     { 
       st = st + "ThePropertyInTheTable =" + element + "||"; 
     } 

     return st; 
} 

Tôi hy vọng bạn hiểu tôi và rằng tôi đã giúp một ai đó :)

+0

Giải pháp này dẫn đến sự cố khi yêu cầu quá dài. Vì vậy, tôi tìm thấy một giải pháp bằng cách sử dụng AddQueryOption và sử dụng $ lọc như thế này: DataServiceQuery ordersQuery = (DataServiceQuery ) this.context.CLIENTS.AddQueryOption ("$ filter", MyFilter()); – ihebiheb

+0

Không sử dụng chữ hoa VÀ. nó dẫn đến và lỗi. sử dụng và không AND. – ihebiheb

3

Dưới đây là nhận thức của tôi về trong đó() Phương pháp, để lọc bộ sưu tập IQueryable bởi một tập hợp các thực thể chọn:

public static IQueryable<T> WhereIn<T,TProp>(this IQueryable<T> source, Expression<Func<T,TProp>> memberExpr, IEnumerable<TProp> values) where T : class 
    { 
     Expression predicate = null; 
     ParameterExpression param = Expression.Parameter(typeof(T), "t"); 

     bool IsFirst = true; 

     // Create a comparison for each value eg:     
     // IN: t => t.Id == 1 | t.Id == 2     

     MemberExpression me = (MemberExpression) memberExpr.Body; 
     foreach (TProp val in values) 
     { 
      ConstantExpression ce = Expression.Constant(val); 


      Expression comparison = Expression.Equal(me, ce); 

      if (IsFirst) 
      { 
       predicate = comparison; 
       IsFirst = false; 
      } 
      else 
      { 
       predicate = Expression.Or(predicate, comparison); 
      } 
     } 

     return predicate != null 
      ? source.Where(Expression.Lambda<Func<T, bool>>(predicate, param)).AsQueryable<T>() 
      : source; 
    } 

Và gọi phương thức này trông giống như:

IQueryable<Product> q = context.Products.ToList(); 

var SelectedProducts = new List<Product> 
{ 
    new Product{Id=23}, 
    new Product{Id=56} 
}; 
... 
// Collecting set of product id's  
var selectedProductsIds = SelectedProducts.Select(p => p.Id).ToList(); 

// Filtering products 
q = q.WhereIn(c => c.Product.Id, selectedProductsIds); 
+2

Rất đẹp. Tuy nhiên nó cung cấp cho một kết quả bất ngờ với một mảng trống như đầu vào. Bạn sẽ không mong đợi gì ở trong mảng trống mà không có kết quả, nhưng thay vào đó nó trả về mọi thứ. Với ý nghĩ đó, tôi đã thay đổi câu lệnh trả về thành: vị từ trả về! = Null ? source.Where (Expression.Lambda > (predicate, param)). AsQueryable () : source.Where (x => false) .AsQueryable (); –

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