2012-12-28 40 views
5

Tôi đang chạy vào một vấn đề với pseudoquery sau:Hai LINQ truy vấn tương tự, hoàn toàn khác nhau tạo ra SQL

var daily = from p in db.table1 
      group p by new 
      { 
       key1, 
       key2 
      } into g 
      join d in db.table2 
      on new { p.key1, p.key2 } equals { d.key1, d.key2 } 
      select new 
      { 
       col1 = g.Key.key1 
       col2 = g.Sum(a => a.column2) 
       col3 = d.column3 
      }; 

Nó chạy nhưng câu lệnh SQL được tạo ra mà LINQ gửi đến SQL Server là ngớ ngẩn. Việc triển khai thực tế sau một thiết lập tương tự như trên với 7 hoặc nhiều cột hơn mà mỗi cột có một phép tính .Sum(). SQL được tạo ra có khoảng 10-11 câu lệnh SELECT lồng nhau không có INNER JOIN và, tất nhiên, chạy mãi mãi.

Tôi đã thử nghiệm ra một thực hiện truy vấn:

var daily = from p in 
       (from p in db.table1 
       group p by new 
       { 
        key1, 
        key2 
       } into g 
       select new 
       { 
        col1 = g.Key.key1, 
        col2 = g.Sum(a => a.column2) 
       }) 
      join d in db.table2 
      on new { p.key1, p.key2 } equals new { d.key1, d.key2 } 
      select new 
      { 
       col1 = p.col1, 
       col2 = p.col2, 
       col3 = d.column3 
      }; 

Phiên bản này tạo ra SQL xa hợp lý hơn với một đơn SUB-SELECT và một INNER JOIN statement (nó cũng chạy damn gần ngay lập tức). Điều tôi ghét về điều này là truy vấn LINQ đầu tiên, IMHO, xa hơn về phía trước và ngắn gọn trong khi thứ hai có vẻ khá dư thừa kể từ khi tôi phải xác định tất cả các cột tôi muốn từ table1 hai lần.

Tại sao hai truy vấn tương tự này thực hiện quá khác nhau trên máy chủ và tại sao truy vấn 2 kết thúc hiệu quả hơn rất nhiều ngay cả khi mã của nó kém rõ ràng hơn?

Có cách nào để tôi có thể viết lại truy vấn đầu tiên hiệu quả như lần thứ hai không?

+0

Bạn có thể đăng SQL của cả hai phiên bản không? – usr

+0

@usr Chắc chắn, hãy để tôi cố gắng để làm sạch nó lên một chút đầu tiên như tôi đã làm cho các truy vấn LINQ. – Kittoes0124

+0

@Kittoes Bạn có thể sử dụng [** LinqPad **] (http://www.linqpad.net/) để viết LINQ và lấy mã Lambda và SQL – balexandre

Trả lời

6

LINQ 2 SQL có một vấn đề với các mô hình sau:

from t in table 
group t by key into g 
from t in g //"ungroup" the grouping - this is causing a problem 
select ... 

Tôi nghĩ join của bạn được kích hoạt đó bởi vì nó "ungroups" các nhóm. Lưu ý rằng một LINQ tham gia là một GroupJoin là không thể trình bày trong SQL. Hãy suy nghĩ về nó: Làm thế nào bạn sẽ dịch truy vấn ví dụ của tôi? Bạn phải tham gia table vào phiên bản được nhóm của table gây ra sự thừa dự điên rồ.

Tôi đã gặp sự cố này một vài lần. Bạn đã tìm thấy đúng công việc xung quanh: Ép buộc một phép chiếu để ngăn chặn mô hình này xảy ra.

Có một phiên bản hơi ít lúng túng:

var daily = from p in db.table1 
      group p by new 
      { 
       key1, 
       key2 
      } into g 
      select new 
      { 
       col1 = g.Key.key1, 
       col2 = g.Sum(a => a.column2) 
      } into p 
      join d in db.table2 on new { p.key1, p.key2 } equals new { d.key1, d.key2 } 
      select new 
      { 
       col1 = p.col1, 
       col2 = p.col2, 
       col3 = d.column3 
      }; 

Các tổ được lấy ra bởi ít được biết đến select x into y cú pháp.

+0

Chết tiệt, tôi thực sự hy vọng rằng đó không phải là câu trả lời. Tôi thực sự ghét phải xác định tất cả các cột của tôi trong table1 hai lần chỉ để có được một cột ra khỏi table2. Nhưng tôi cho rằng nó không giống như tôi có bất kỳ sự lựa chọn nào trong vấn đề. – Kittoes0124

+0

@Khoa cũng là cảm giác của tôi về điều này. Mặt khác LINQ tiết kiệm rất nhiều công việc mà nó là giá trị dung nạp các trường hợp cạnh khó chịu. Tôi muốn nhóm EF sẽ cung cấp hỗ trợ LINQ có thẩm quyền hoặc L2S đã không bị bỏ rơi ... – usr

+1

Ồ, chắc chắn rồi. Số lượng công việc khác mà LINQ tiết kiệm là hoàn toàn vô lý nên nó hoàn toàn xứng đáng với những thứ như thế này khi nó xảy ra.Chỉ khiến tôi điên rồ xác định 10 cột + hai lần không có lý do thực sự. Cảm ơn bạn rất nhiều vì đã giải thích tại sao nó xảy ra. – Kittoes0124

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