2009-05-19 28 views
7

Tôi đang viết một hệ thống ASP.net dựa trên thẻ. Sử dụng chương trình db sau:LINQ options.loadwith problem

Topic <many-many> TagTopicMap <many-many> Tag

Về cơ bản nó là một phương pháp 3NF (toxi) mà tôi tìm thấy từ sau: http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html

Dưới đây là đoạn mã tôi có:

DataLoadOptions options = new DataLoadOptions(); 
     options.LoadWith<Topic>(t => t.TagTopicMaps); 
     options.LoadWith<TagTopicMap>(tt => tt.Tag); 
     var db = new lcDbDataContext(); 
     db.LoadOptions = options; 
     db.Log = w; 

     var x = from topic in db.Topics 
       orderby topic.dateAdded descending 
       select topic; 

     ViewData["TopicList"] = x.Take(10); 

Khi tôi thực hiện điều này, kết quả là tốt, nhưng nó đi kèm với 11 truy vấn SQL đơn, một để nhận danh sách 10 chủ đề hàng đầu:

SELECT TOP (10) [t0].[Id], [t0].[title], [t0].[dateAdded] 
FROM [dbo].[Topics] AS [t0] ORDER BY [t0].[dateAdded] DESC 
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30729.1 

Và 10 trong số những người khác để biết chi tiết về các thẻ riêng lẻ.

tôi đã cố gắng để chuyển đổi hai câu loadwith và tắt, và tìm thấy những điều sau đây xảy ra:

loadwith<topic> : no difference for on or off. 
loadwith<tagtopicmap>: 11 Queries when on, much more when off. 

Nói tóm lại, CHỈ tùy chọn loadwith thứ hai đang làm việc như mong đợi. Người đầu tiên không có hiệu lực!

Tôi cũng đã cố gắng tạo kết quả ToList(). Nhưng thậm chí còn nhiều vấn đề sắp xảy ra: đối với phần chi tiết thẻ, nó chỉ truy xuất các mục UNIQUE, tất cả các thẻ lặp lại đó (cùng một thẻ có thể xuất hiện trong một số chủ đề!) Bị truy vấn bỏ qua.

Một điều cuối cùng, đây là đoạn code tôi sử dụng trong aspx để lấy dữ liệu, trong trường hợp làm cho ToList kết quả(), tôi thay đổi (IQueryable) đến (IList):

<% foreach (var t in (IQueryable)ViewData["TopicList"]) 
     { 
      var topic = (Topic)t; 

    %> 
    <li> 
     <%=topic.title %> || 
     <% foreach (var tt in (topic.TagTopicMaps)) 
      { %> 
       <%=tt.Tag.Name%>, 
       <%} %> 
    </li> 
    <% 
     } 
    %> 

Trả lời

5

Ngắn câu trả lời là: LinqToSql có một số quirks như thế này, và đôi khi bạn phải sử dụng work-around ...

Tùy chọn Linq2Sql LoadWith chỉ đơn giản là gây ra một kết nối bên trong giữa các bảng cơ sở dữ liệu, do đó bạn có thể buộc hành vi tương tự bằng cách viết lại LINQ của bạn tuyên bố một cái gì đó như (xin vui lòng tha thứ cho bất kỳ lỗi chính tả, tôi được sử dụng để viết Linq trong VB cú pháp ...):

var x = from topic in db.Topics 
     join topicMap in topic.TagTopicMaps 
     orderby topic.dateAdded descending 
     group topicMap by topicMap.topic into tags = Group; 

Cú pháp này có thể sai lầm khủng khiếp, nhưng ý tưởng cơ bản là bạn buộc Linq2Sql đánh giá sự kết hợp giữa Chủ đề và TagTopicMaps rồi sử dụng nhóm (hoặc "nhóm tham gia", "cho phép", v.v.) giữ nguyên chế độ thừa kế đối tượng trong tập kết quả.

+0

Nó không phải luôn luôn là INNER JOIN. Nếu * tất cả các trường tham gia là null-khả năng * thì nó sẽ là một LEFT JOIN - nó là một "tính năng sai" không có giấy tờ mà INNER JOIN tạo ra ngay cả khi các trường nối * chứa một số (nhưng không phải tất cả) null-có thể cột*. –

1

Đặt EnabledDefferedLoad trên lớp dữ liệu văn bản của bạn thành sai.

0

Sự cố trong trường hợp của bạn là Take (10). Dưới đây là từ miệng của ngựa:

https://connect.microsoft.com/VisualStudio/feedback/details/473333/linq-to-sql-loadoptions-ignored-when-using-take-in-the-query

Cách giải quyết đề nghị là thêm Skip (0). Điều đó không hiệu quả đối với tôi, nhưng Skip (1) đã làm việc. Vô ích như nó có thể được, ít nhất tôi biết vấn đề của tôi là ở đâu.