Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can someone explain why these two linq queries return different results?

I have two linq (to EF4) queries, which return different results. The first query contains the correct results, but is not formatted/projected right.

the second query is what i want but it missing some data.

Schema

alt text http://img220.imageshack.us/img220/9678/schema.png

Query 1

var xxxx = (from cp in _connectedClientRepository
            .GetConnectedClients(new[] { "LogEntry", "LogEntry.GameFile" })
            .AsExpandable()
            .Where(predicate)
            select cp)
    .ToList();

alt text http://img231.imageshack.us/img231/6541/image2ys.png

Notice the property GameFile . It is not null. This is great :) Notice the linq query? I'm eager loading a LogEntry and then eager loading a GameFile (for each eager loaded LogEntry).

This is what i'm after -> for each LogEntry that is eager loaded, please eager load the GameFile. But this projection result is wrong...

Ok.. next...

Query 2

var yyy = (from cp in _connectedClientRepository
            .GetConnectedClients(new[] { "LogEntry", "LogEntry.GameFile" })
            .AsExpandable()
            .Where(predicate)
        select cp.LogEntry)
    .ToList();

alt text

NOTE: the image above has a typo in it ... please note the include associations typed code is correct (ie. LogEntry.GameFile) while the image has it typo'd.

Correct projection now -> all LogEntries results. But notice how the GameFile property is now null? I'm not sure why :( I thought i correctly eager loaded the correct chain. So this is the correct projection but with incorrect results.

Obligatory Repository code.

public IQueryable<ConnectedClient> GetConnectedClients(
    string[] includeAssociations)
{
    return Context.ConnectedClients
        .IncludeAssociations(includeAssociations)
        .AsQueryable();
}

public static class Extensions
{
    public static IQueryable<T> IncludeAssociation<T>(
        this IQueryable<T> source, string includeAssociation)
    {
        if (!string.IsNullOrEmpty(includeAssociation))
        {
            var objectQuery = source as ObjectQuery<T>;

            if (objectQuery != null)
            {
                return objectQuery.Include(includeAssociation);
            }
        }

        return source;
    }

    public static IQueryable<T> IncludeAssociations<T>(
        this IQueryable<T> source, params string[] includeAssociations)
    {
        if (includeAssociations != null)
        {
            foreach (string association in includeAssociations)
            {
                source = source.IncludeAssociation(association);
            }
        }

        return source;
    }
}

Updates

  • 1 : Fixed some typo's in noticed in the code samples.
  • 2 : Added repository code to help anyone who is confused.
like image 869
Pure.Krome Avatar asked Feb 15 '10 15:02

Pure.Krome


1 Answers

I suspect Craig Stuntz' suggestion may work, but if it doesn't, the following should certainly work:

 var xxxx =_connectedClientRepository
        .GetConnectedClients(new[] { "LogEntry", "LogEntry.GameFile" })
        .AsExpandable()
        .Where(predicate)
        .ToList() // execute query
        .Select(cp => cp.LogEntry); // use linq-to-objects to project the result
like image 117
jeroenh Avatar answered Sep 22 '22 20:09

jeroenh