2009-05-19 16 views
7

Estoy escribiendo un sistema ASP.net basado en etiquetas. Usando el siguiente esquema db:LINQ options.loadwith problem

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

Básicamente se trata de un enfoque 3NF (toxi) que he encontrado entre los siguientes: http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html

Aquí está el fragmento de código que tengo:

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

Cuando ejecuto esto, el resultado está bien, pero aparece con 11 consultas SQL individuales, una para obtener la lista de los 10 temas principales:

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 

Y 10 de esos otros para obtener detalles de las etiquetas individualmente.

Me trataron de cambiar las dos declaraciones LoadWith de encendido y apagado, y hallaron las siguientes cosas:

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

En resumen, sólo la segunda opción LoadWith está funcionando como se esperaba. ¡El primero no tiene ningún efecto!

También intenté hacer el conjunto de resultados ToList(). Pero surge aún más problema: para la parte del detalle de las etiquetas, solo recupera esos elementos ÚNICOS, todas esas etiquetas repetitivas (¡esa misma etiqueta puede aparecer en un número de tema, por supuesto!) Son descartadas por la consulta.

Una última cosa, es el código que utilicé en aspx para recuperar los datos, en caso de hacer el tolist resultado(), 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> 
    <% 
     } 
    %> 

Respuesta

5

El corto la respuesta es: LinqToSql tiene varios caprichos como este, y algunas veces tiene que usar soluciones temporales ...

La opción Linq2Sql LoadWith simplemente causa una unión interna entre las tablas de la base de datos, por lo que puede forzar un comportamiento similar al reescribir su Linq declaración a algo así como (por favor perdone cualquier error tipográfico, estoy acostumbrado a escribir Linq en sintaxis 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; 

Esta sintaxis puede ser muy mal, pero la idea básica es que se fuerza Linq2Sql para evaluar la unión entre los temas y TagTopicMaps, y luego utiliza la agrupación (o "unirse a grupo", "vamos", etc.) para preservar la jerarquía de objetos en el conjunto de resultados.

+0

No siempre es una UNIÓN INTERNA. Si * todos los campos de unión son nula-able * entonces será una JOIN IZQUIERDA - es cuestionable una "característica errónea" no documentada que INNER JOIN generará incluso cuando los campos de unión * contengan algunos (pero no todos) null-able columnas *. –

1

Establezca EnabledDefferedLoad en su clase de datacontext en falso.