2011-10-21 6 views
11

Tôi có một truy vấn kéo từ một cơ sở dữ liệu:Làm cách nào tôi có thể đặt thuộc tính trên tất cả các mục từ truy vấn LINQ với các giá trị từ một đối tượng khác cũng được lấy từ truy vấn?

List<myClass> items = new List<myClass>(from i in context 
         select new myClass 
         { 
          A = i.A, 
          B = "", // i doesn't know this, this comes from elsewhere 
          C = i.C 
         } 

Tôi cũng có một truy vấn làm một điều tương tự:

List<myClass2> otherItems = new List<myClass2>(from j in context 
          select new myClass2 
          { 
           A = j.A, // A is the intersection, there will only be 1 A here but many A's in items 
           B = j.B 
          } 

Trên thực tế các lớp này là lớn hơn và truy vấn nhiều dữ liệu được tách ra không chỉ bởi cơ sở dữ liệu nhưng bởi máy chủ là tốt. Có thể sử dụng truy vấn LINQ để điền thuộc tính B cho tất cả items trong đó các mục có giao nhau không? Tất cả các biến vị ngữ LINQ được xây dựng chỉ xuất hiện để thực hiện tổng hợp, lựa chọn hoặc biểu thức bool.

Trong não của tôi, tôi có một cái gì đó như thế này, nhưng đây là tất cả off:

items.Where(x => x.B = (otherItems.Where(z => z.A == x.A).Single().B)); 

Hoặc tôi là lố bịch với cố gắng để làm công việc này trong LINQ và chỉ nên từ bỏ nó trong lợi của một vòng lặp for nơi thiết lập thực tế trở nên tầm thường? Bởi vì thời hạn tôi sẽ phải dùng đến vòng lặp for (và có lẽ nó sẽ kết thúc được nhiều hơn nữa có thể đọc được trong thời gian dài anyway), nhưng nó có thể làm điều này? Một phương pháp mở rộng có cần thiết để thêm một vị từ đặc biệt để cho phép điều này không?

+0

Tôi sẽ nói vòng lặp của bạn là một triển khai tốt. – JonH

+0

Bạn có thể hiển thị một tập dữ liệu đơn giản có cấu trúc chính mà bạn đang tìm kiếm không? Truy vấn cuối cùng cố gắng đạt được là gì? – Tormod

+0

@Tormod: Truy vấn thứ hai chứa biến 'B'. Tôi đang tìm một biến vị ngữ hoặc phương pháp mở rộng sẽ thực hiện dân số của biến 'B' trong tập hợp đầu tiên. –

Trả lời

21

LINQ được thiết kế cho truy vấn. Nếu bạn đang cố gắng để đặt điều, bạn chắc chắn nên sử dụng vòng lặp (có thể là foreach). Điều đó không có nghĩa là bạn sẽ không thể sử dụng LINQ như một phần của vòng lặp đó, nhưng bạn không nên cố gắng áp dụng một hiệu ứng phụ trong chính LINQ.

+0

Một mâu thuẫn có thể là việc sử dụng chèn, cập nhật và xóa. Điều này cho thấy rằng nó có thể được thiết kế cho nhiều hơn là chỉ truy vấn. Tôi có thể đồng ý rằng các biến vị ngữ mặc định được đóng gói trong khung công tác chỉ dành riêng cho truy vấn, nhưng nó làm cho tôi tự hỏi liệu ứng dụng của một phương pháp mở rộng toàn diện có được kéo dài ra ngoài các truy vấn đơn giản hay không. Tôi hoàn toàn nhận ra sự khác biệt giữa "có thể" và "nên". Tại thời điểm này, tôi đang khám phá khả năng (và cố gắng lấp đầy khoảng trống trong kiến ​​thức LINQ của riêng tôi). –

+0

@ JoelEtherton: Chúng là một phần của việc bổ sung cho các nhà cung cấp LINQ cụ thể - chúng không phải là một phần của chính LINQ. Mỗi nhà cung cấp LINQ là "phần truy vấn theo mẫu LINQ" cộng với các phần khác được nhà cung cấp cụ thể. –

+0

Tôi sẽ nghĩ rằng một cái gì đó như thế này sẽ phù hợp trong LINQ to Objects, nhưng tôi có thể hiểu tại sao nó không phải là một thực hiện mặc định. Vì vậy, theo ý kiến ​​của bạn, nếu tôi có nhu cầu cho một cái gì đó như thế này mà có thể biện minh cho chi phí nỗ lực, nó sẽ là cần thiết (khôn ngoan?) Để thực hiện LINQ tùy chỉnh của riêng tôi để cung cấp MyNamespace? –

0

Truy vấn các mục khác trước tiên. Thực hiện một ToDictionary() trên kết quả. Sau đó, khi truy vấn cơ sở dữ liệu, hãy thực hiện điều này:

var items = from i in context 
    select new myClass 
    { A = i.A, 
    B = otherItems[i.A], 
    C = i.C 
    } 
+0

LINQ không cho phép kết hợp các truy vấn dữ liệu và truy vấn trong bộ nhớ. Nó sẽ biên dịch nhưng nó sẽ tạo ra một ngoại lệ thời gian chạy vì các chuỗi cục bộ không thể được sử dụng trong các bối cảnh dữ liệu.Để làm cho phần truy vấn dữ liệu hoạt động, nó sẽ phải thực hiện điều đó và đưa nó đến một chuỗi cục bộ và sau đó thực hiện lựa chọn khác sẽ tạo một truy vấn dư thừa (cái mà tôi sẽ sử dụng LINQ để tránh). –

+0

Phải. Việc đóng cửa cục bộ sẽ không dịch thông qua cây biểu thức vào nhà cung cấp truy vấn LINQ. Vâng, sau đó nó phụ thuộc vào cách bạn muốn truy vấn để thực hiện. Nếu bạn muốn truy vấn được đánh giá lười biếng, bạn có nguy cơ đánh nó nhiều lần khi lặp lại. Nhưng tôi cho rằng bạn có thể làm điều đó với src.Select (remdata => new {}). AsEnumerable() .Chọn (localdata => new {A = ld.a, B = otherItems [ld.a], C = ld .c}) – Tormod