2009-05-19 12 views
7

Piszę system ASP.net oparty na tagach. Stosując następujący schemat DB:LINQ options.loadwith problem

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

Zasadniczo jest to podejście 3NF (Toxi) które znalazłem z następujących opcji: http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html

Oto fragment kodu mam:

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); 

Po wykonaniu tego, wynik jest w porządku, ale pojawia się 11 pojedynczych zapytań SQL, jeden dla uzyskania listy 10 najważniejszych tematów:

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 

I 10 z nich innych w celu uzyskania szczegółowych informacji o tagach pojedynczo.

próbowałem zamienić dwa oświadczenia loadwith i wyłączać, a okazało się, że następujące konsekwencje:

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

W skrócie tylko druga opcja loadwith działa zgodnie z oczekiwaniami. Pierwszy nie ma żadnego efektu!

Próbowałem również utworzyć zestaw wyników ToList(). Ale pojawia się jeszcze więcej problemów: w przypadku części szczegółów tagów, pobiera ona tylko te UNIKALNE pozycje, wszystkie te powtarzające się znaczniki (ten sam tag może pojawić się w wielu tematach, oczywiście!) Są odrzucane przez zapytanie.

Ostatnią rzeczą, w następującym kodzie użyłem w aspx do pobierania danych, w przypadku dokonywania ToList wynik(), I zmiana (IQueryable) do (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> 
    <% 
     } 
    %> 

Odpowiedz

5

Krótki odpowiedź brzmi: LinqToSql ma kilka dziwactw jak to, a czasami trzeba użyć obejść ...

Opcja LoadWith Linq2Sql po prostu powoduje wewnętrzne sprzężenie między tabelami bazy danych, dzięki czemu można wymusić podobne zachowanie, przepisując Linq oświadczenie do czegoś podobnego (proszę wybaczyć wszelkie literówki, jestem przyzwyczajony do pisania Linq w składni VB ...):

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

Ta składnia może być okropnie błędna, ale podstawową ideą jest wymuszanie na Linq2Sql oceny sprzężenia między tematami i TagTopicMaps, a następnie użycie grupowania (lub "łączenia grup", "let", itp.) Do zachowaj dziedziczność obiektu w zestawie wyników.

+0

Nie zawsze INNER DOŁĄCZ. Jeśli * wszystkie pola łączenia będą miały wartość null *, wówczas będzie to LEFT JOIN - jest to prawdopodobnie nieudokumentowana "nieprawidłowa funkcja", którą INNER JOIN generuje, nawet jeśli pola łączenia * zawierają niektóre (ale nie wszystkie) null-stanie kolumny *. –

1

Ustawia EnabledDefferedLoad na swojej klasie datacontext na false.