2012-12-16 13 views
5

Tôi đang sử dụng mã BAGA từ cuốn sách DbContext của Julie Lerman. Tôi muốn tạo lại truy vấn sql sau đây trong LINQ và đặt kết quả trong một bộ sưu tập Danh sách và đang gặp sự cố. http://learnentityframework.com/downloads/Điều khoản trên bộ sưu tập

SELECT * FROM baga.Locations d 
LEFT JOIN Lodgings l ON d.LocationID = l.destination_id 
WHERE d.Country = 'usa' 
AND (l.MilesFromNearestAirport > 5 or l.MilesFromNearestAirport is null) 

Vì vậy, bằng tiếng Anh, có được tất cả các địa điểm (điểm đến) mà là ở Mỹ và bao gồm tất cả các chỗ ở có liên quan nơi MilesFromNearestAirport> 5

Cú pháp không biên dịch nhưng tôi đã hy vọng cho một cái gì đó tương tự như bên dưới

var dests = context.Destinations 
    .Where(d => d.Country == "USA" && d.Lodgings.Where(l => l.MilesFromNearestAirport > 5)) 
    .Select(d => d) 
    .ToList(); 

Bất kỳ ý tưởng nào?

+1

Lựa chọn hợp lệ. – usr

+0

Cách tiếp cận là sai vì sự tham gia bên trái. Bạn cần phải làm một cái gì đó tương tự: .Where (d => d.Country == "USA" && (d.Lodgings.Count == 0 || d.Lodgings.Any (l => l.MilesFromNearestAirport == null || l.MilesFromNearestAirport> 5)) Điều này sẽ lấy các vị trí chính xác Khi truy cập vào các lodgings, cùng một biểu thức trong các điều khoản chỗ ở sẽ cần phải được sử dụng để lấy các chỗ ở áp dụng. Theo như tôi biết, khung thực thể chỉ hỗ trợ tham gia bên trong Một lưu ý khác, truy vấn này sẽ khá đơn giản trong nhibernate – Shelakel

+0

Cả hai giải pháp này đều không hoạt động Shelakel, bạn đã sử dụng NHibernate nhiều chưa? Bạn có nên giới thiệu nó qua EF? – orangesherbert

Trả lời

7

Như @Sampath nói, điều này thường được thực hiện với các thuộc tính điều hướng nhưng tôi tin rằng mã của anh ấy không chính xác làm những gì bạn muốn. Điều này (tôi nghĩ) gần hơn:

var dests = context.Destinations 
      .Where(d => d.Country == "USA") 
      .Select(d => 
       new { d, 
        RemoteLodgings = d.Lodgings 
         .Where(l => l.MilesFromNearestAirport > 5)} 
      .ToList(); 

Nhưng nó vẫn không làm những gì bạn muốn nếu tôi yêu cầu thư của bạn. Bạn muốn vị trí có chỗ ở là bao gồm, tức là các thuộc tính điều hướng được tải một phần. Điều này có thể thuận tiện khi các thực thể được sắp xếp theo thứ tự và được gửi đến một máy khách (web) trong một gói. (Mặc dù phương pháp trên cũng có thể được chấp nhận cho điều đó).

Nhưng có thể tạo bộ sưu tập với các thuộc tính điều hướng được tải một phần.

Cuốn sách, ở trang 40, cho thấy cách bạn có thể tải một phần thuộc tính điều hướng của một thực thể (viết tắt là context.Entry(entity).Collection(e => e.Children).Query().Where(condition). Nhưng như đã nói, đó chỉ là một ví dụ. Đây không phải là phương pháp tốt nhất để làm điều đó cho một tập hợp tổ chức

điều buồn cười là (như là một đồng nghiệp của tôi phát hiện ra), bạn có thể dễ dàng làm điều đó cho một tập hợp các thực thể bằng cách tải các yếu tố bộ sưu tập cần thiết vào bối cảnh riêng biệt:.

var lodgings = context.Lodgings 
       .Where(l => l.MilesFromNearestAirport > 5 
         && l.Destination.Country == "USA") 
       .ToList(); 

Bây giờ nếu bạn vòng qua context.Destinations.Where(d => d.Country == "USA") bạn sẽ thấy rằng chỗ ở của họ được tải bằng những cái ">5 ". Có lẽ bởi vì tại thời điểm này, EF đã thực hiện sửa lỗi quan hệ. (Tải Lazy bị vô hiệu hóa, vì tải lười sẽ tải đầy đủ các thuộc tính điều hướng).

Sửa (sau khi bình luận của bạn)
tôi không thể đồng ý hơn khi bạn nói nó là một chút của một hack. Trên thực tế tôi quên đề cập đến rằng ở nơi đầu tiên. Vấn đề là toàn bộ cơ chế sụp đổ khi việc tải chậm xảy ra sẽ được kích hoạt bởi một người không biết mã của cái gì. Tôi không thích mã phụ thuộc vào nhà nước theo cách không rõ ràng. Vì vậy, tôi sẽ luôn luôn thích cách tiếp cận đầu tiên.

+0

Xin chào Gert, cảm ơn vì một câu trả lời tuyệt vời (loại!). – orangesherbert

+0

Nói rằng tôi đã cải thiện mã của bạn một chút bằng cách loại bỏ var lodgings và thay thế. ToList() bằng Load() như tôi đoán đó là tất cả những gì tôi cần làm. Một chút hạnh phúc hơn với nó bây giờ thực sự. – orangesherbert

+0

Ồ, và tôi phải xóa từ khóa ảo để tắt tải chậm (như bạn đã nói) – orangesherbert

2

Thông thường việc này được thực hiện sử dụng các thuộc tính điều hướng được tải khi bạn nhận thực thể.

Tuy nhiên bạn cũng có thể làm điều này với những điều sau đây:

(from d in baga.Locations 
from l in Lodgings 
where (d.LocationID == l.destination_id) 
where (d.Country = 'usa' && (l.MilesFromNearestAirport > 5 || l.MilesFromNearestAirport == null)) 
select d) 
.ToList(); 

Tôi hy vọng điều này sẽ giúp cho bạn.

+0

Xin lỗi, tập kết quả không chính xác. Điều này không hạn chế MilesFromNearestAirport> 5 cũng không bao gồm những bản ghi mà không có các tệp Lodgings liên quan. Là nó chỉ cho tôi hoặc là LINQ chỉ đau đớn cho sql đơn giản như thế này? – orangesherbert

1

Cách sử dụng LINQ join?

var res = from d in context.Destinations 
      join l in context.Lodgings on d.LocationID equals l.destination_id 
      where (l.MilesFromNearestAirport > 5 || l.MilesFromNearestAirport == null) 
       && d.Country = "usa" 
      select new { 
        Destination = d, 
        Location = l 
        }