2009-05-19 7 views
7

Sto scrivendo un sistema ASP.net basato su tag. Utilizzando il seguente schema db:LINQ options.loadwith problem

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

Fondamentalmente si tratta di un approccio 3NF (toxi) che ho trovato tra i seguenti: http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html

Qui è il frammento di codice che ho:

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

Quando eseguo ciò, il risultato è soddisfacente, ma vengono visualizzate 11 query SQL singole, una per ottenere l'elenco dei 10 argomenti principali:

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 

E 10 di questi altri per ottenere i dettagli dei tag singolarmente.

ho cercato di cambiare le due affermazioni loadwith on e off, e trovarono le seguenti cose accadono:

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

In breve, solo la seconda opzione loadwith funziona come previsto. Il primo non ha alcun effetto!

Ho anche provato a rendere il set di risultati ToList(). Ma ancora più problema viene fuori: per la parte relativa ai tag, recupera solo quegli elementi UNICI, tutti quei tag ripetuti (lo stesso tag potrebbe apparire in un certo numero di argomenti, ovviamente!) Vengono eliminati dalla query.

Un'ultima cosa, segue è il codice che ho usato in aspx per recuperare i dati, in caso di rendere il ToList risultato(), cambio (IQueryable) a (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> 
    <% 
     } 
    %> 

risposta

5

Il corto La risposta è: LinqToSql ha diversi capricci come questo, ea volte devi usare il work-arounds ...

L'opzione Linq2Sql LoadWith causa semplicemente un inner join tra le tabelle del database, quindi puoi forzare un comportamento simile riscrivendo il tuo Linq dichiarazione a qualcosa come (per favore perdona qualsiasi refuso, sono abituato a scrivere Linq in sintassi 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; 

Questa sintassi può essere terribilmente sbagliato, ma l'idea di base è che si forza Linq2Sql per valutare l'unione tra argomenti e TagTopicMaps, e quindi utilizzare il raggruppamento (o "gruppo di join", "lascia", ecc) per preservare l'oggetto gerarchia nel set di risultati.

+0

Non è sempre UN INTERVENTO INTERIORE. Se * tutti i campi di join sono null-able * allora sarà UN SINISTRA SINISTRO - è discutibilmente una "mis-feature" non documentata che l'INNER JOIN genera anche quando i campi di join * contengono alcuni (ma non tutti) null-able colonne *. –

1

Impostare EnabledDefferedLoad sulla classe datacontext su false.