2016-01-08 12 views
10

tôi có một danh sách IQueryable với loại COLOURS lớpbiểu thức Lambda đặt hàng qua và đưa vấn đề

IQueryable<COLOURS> renkler = dbcontext.colours.Select(s=>new COLOURS{ .... 

Tôi muốn nhận được ngẫu nhiên 2 hàng, tôi đang sử dụng khối mã này để làm điều này:

renkler.OrderBy(o => Guid.NewGuid()).Take(2); 

Tôi muốn 2 hàng nhưng đôi khi nó có 3 hàng hoặc 5 hàng:

enter image description here

Take(2) không hoạt động - vấn đề là gì?

tôi đã nhận thấy một cái gì đó khi tôi kiểm tra

var result = NewProducts().OrderBy(o => Guid.NewGuid()).Take(2); 
int result_count = result.Count(); //This value is 2 :D 
            //but ToList() result 5 :D 

Toàn bộ phương pháp:

public IQueryable<COLOURS> NewProducts() 
{ 
    DateTime simdi = DateTime.Now; 
    DateTime simdi_30 = DateTime.Now.AddDays(-30); 

    var collection_products = DefaultColours() 
          .Where(w => ((w.add_date.Value >= simdi_30 && w.add_date.Value <= simdi) || w.is_new == true)) 
          .OrderByDescending(o => o.add_date).Take(200) 
          .Select(s => new COLOURS 
          { 
           colour_code = s.colour_code, 
           model_code = s.products.model_code, 
           sell_price = (decimal)s.sell_price, 
           market_price = (decimal)s.market_price, 
           is_new = (bool)s.is_new, 
           product_id = (int)s.product_id, 
           colour_name = s.name, 
           product_name = s.products.name, 
           description = s.products.description, 
           img_path = s.product_images.FirstOrDefault(f => f.is_main == true).img_path, 
           category_id = (int)s.category_relations.FirstOrDefault().category_id, 
           display_order = (short)s.display_order, 
           section_id = (int)s.products.section_id, 
           stock_amount = s.pr_sizes.Where(w => w.is_active == true && w.quantity >= 0).Count() > 0 ? (int)s.pr_sizes.Where(w => w.is_active == true && w.quantity >= 0).Sum(s2 => s2.quantity) : 0, 
                     section_name = s.products.pr_sections.name, 

          });  
    return collection_products; 
} 

public IQueryable<COLOURS> RandomNewProducts(int n) 
{ 
    var result = NewProducts().OrderBy(o => Guid.NewGuid()).Take(n); 
    int result_count = result.Count(); //2 
    //When I run this method it's getting 5 rows    
    return result; 
} 
+0

Cũng có thể hoặc không ảnh hưởng đến truy vấn cuối cùng. Bạn cũng có thể hiển thị truy vấn được hiển thị khi di chuột qua 'kết quả' không? Tôi mong chờ một cái gì đó như 'SELECT TOP 2 * FROM (SELECT TOP 200 * FROM ...)'. – CodeCaster

+7

@theEmge: Rất nhiều người đang cố gắng giúp bạn ở đây và tất cả họ đều nói "hiển thị cho tôi mã". Họ muốn mã để họ có thể tái tạo các triệu chứng của bạn để tìm ra những gì đang xảy ra. Vui lòng ngừng đặt một đoạn mã một phần trong nhận xét - đặt toàn bộ mã của bạn vào câu hỏi, nếu không bạn chỉ lãng phí thời gian của mọi người. Nếu bạn có thể cắt mã xuống để một cái gì đó đơn giản mà vẫn còn trưng bày vấn đề, rất nhiều càng tốt. –

+2

Điều này giống như phương thức mở rộng Take() trên System.Linq.Enumerable, nhưng nó thực sự? Nó có thể là một phương pháp cùng tên trên một lớp khác không? Vui lòng đăng tất cả mã của bạn, bao gồm các tham chiếu/báo cáo 'sử dụng' và phương thức DefaultColours(). –

Trả lời

2

Đây có thể là không có giải pháp cho bạn, nhưng thật khó để định dạng ý kiến ​​với mã multiline và hình ảnh.

Tôi khá chắc chắn rằng đây là sự cố với nhà cung cấp dữ liệu của bạn. Có lẽ thành phần này không thực hiện cách Take().

Tôi đã cố gắng xây dựng lại chòm sao của bạn nhưng thay vì bất kỳ nhà cung cấp IQueryable nào tôi đã tạo List<> với 500 đối tượng và được gọi là AsQueryable() trên đó để đáp ứng chữ ký của phương thức.

public static IQueryable<COLOURS> DefaultColours() 
    { 
     const int COUNT = 500; 

     List<COLOURS> x = new List<COLOURS>(); 

     var startDate = DateTime.Today.AddDays(-1 * (int)(COUNT/2)); 

     // add 500 date values, and use the date and any random bool value 
     for (int i = 0; i < COUNT; i++) 
      x.Add(new COLOURS() { add_date = startDate.AddDays(i), is_new = i % 3 == 0 }); 

     return x.AsQueryable(); 
    } 

Nhưng khi tôi làm điều này, phương pháp Take() luôn trở về hai mục (khác nhau) mỗi lần - cũng giống như bất cứ ai mong chờ:

debugger view

0

này có thể là do sự o = > Guid.NewGuid() lambda.

Thuật toán sắp xếp yêu cầu một khóa duy nhất được gắn với từng phần tử. Gọi Guid.NewGuid() có nghĩa là bất kỳ phần tử cụ thể nào cũng có thể có nhiều khóa liên kết với nó tùy thuộc vào thời điểm nó được gọi. LINQ cố gắng để có cơ hội trong cách nó hoạt động trên các bộ, vì vậy điều này có thể gây ra ví dụ hai yếu tố thấp nhất đột nhiên không còn là hai phần tử thấp nhất trong quá trình phân loại.

Cân nhắc cố gắng sắp xếp danh sách các số nguyên ngẫu nhiên trong đó các số nguyên đó thay đổi ngẫu nhiên mỗi khi thuật toán sắp xếp tìm cách truy xuất chúng. Cách duy nhất này sẽ làm việc là nếu thuật toán sắp xếp cung cấp một sự bảo đảm để gọi chức năng quan trọng một lần và chỉ một lần cho mọi phần tử.

Tài liệu trên OrderBy không cho biết thuật toán sắp xếp có được phép gọi hàm khóa nhiều lần cho mỗi phần tử hay không, vì vậy tốt nhất là giả sử trường hợp xấu nhất trừ khi bạn có thể chứng minh khác. Như một (hy vọng) cách đơn giản để kiểm tra điều này, nếu bạn có thể tạm thời bao gồm các phím ngẫu nhiên như là một phần tử liên tục của đối tượng COLOR của bạn để thứ tự không thay đổi trong khi sắp xếp, .Take() sẽ bắt đầu hoạt động chính xác như dự định.

Ngoài ra, Guid.NewGuid() không nhanh, vì vậy hãy chuyển thử nghiệm tạm thời đó thành một giải pháp lâu dài sử dụng bộ nhớ nhiều hơn một chút cho mỗi đối tượng có thể cải thiện tốc độ của mã của bạn.