Pergunta

Eu estou escrevendo um sistema ASP.net baseada em tag. Usando o seguinte esquema db:

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

Basicamente, é uma abordagem 3NF (toxi) que encontrei a partir do seguinte: http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html

Aqui está o trecho de código que eu tenho:

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 eu executar isso, o resultado é bom, mas ele vem com 11 consultas SQL individuais, uma para obter a lista dos top 10 tópicos:

    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 desses outros para obter detalhes sobre as tags individualmente.

Eu tentei mudar as duas declarações LoadWith dentro e fora, e encontrou as seguintes coisas acontecem:

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

Em suma, apenas a segunda opção LoadWith está funcionando como esperado. A primeira não tem qualquer efeito!

Eu também tentou fazer o ToList de resultados (). Mas ainda mais problema que sai:. Para a parte etiquetas detalhe, ele só recuperar esses itens exclusivos, todas essas tags de repetição (! Essa mesma tag pode aparecer em uma série de tema, é claro) são descartados pela consulta

Uma última coisa, a seguir é o código que usei no aspx para recuperar os dados, no caso de fazer o ToList resultado (), eu mudança (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>
    <%
        }
    %>
Foi útil?

Solução

A resposta curta é: LinqToSql tem várias peculiaridades como esta, e às vezes você tem que usar soluções alternativas ...

A opção Linq2Sql LoadWith simplesmente provoca uma junção interna entre as tabelas de banco de dados, para que possa forçar um comportamento semelhante por reescrita sua declaração de Linq para algo como (por favor, perdoe quaisquer erros de digitação, eu estou acostumado a escrita Linq na sintaxe 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 sintaxe pode ser terrivelmente errado, mas a idéia básica é que você forçar Linq2Sql para avaliar a associação entre tópicos e TagTopicMaps, e depois usar o agrupamento (ou "grupo juntar-se", "vamos", etc.) para preservar o objeto hierarquia no conjunto de resultados.

Outras dicas

Defina a EnabledDefferedLoad em sua classe datacontext para falso.

O problema no seu caso é Take (10). Aqui é da boca do cavalo:

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

A solução sugerida é a de adicionar SKIP (0). Isso não funcionou para mim, mas ignorar (1) não funcionou. Inútil, pois pode ser, pelo menos eu sei onde o meu problema.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top