Question

I have the following LINQ code used in a unified search function.

var searchObjects =
    from objectA in this.context.DB.objectAs
    join objectB in this.context.DB.objectBs on objectA equals objectB.objectA into objectAB
    from AB in objectAB.Where(o => o.Type == "BasicGroup").DefaultIfEmpty()
    select new { objectA, objectB = AB};

foreach (var searchWord in searchWords)
{
    var searchObjects =
        searchObjects.Where(p => p.objectA.Name.Contains(searchWord) ||
            (p.objectB != null &&
                (p.objectB.Name.Contains(searchWord) ||
                p.objectB.ID.contains(searchWord))));
}

The goal is to look for the search words in objectA's Name field, or in the associated objectB's Name or ID fields. The problem is that when I try to enumerate searchObjects, it just returns a NullReferenceException, with no further details.

The first part of the query returns a proper list of the combination objects (without any filters), so I don't think the problem is with the left join?

I can't figure out what is causing the exception, so any help would be appreciated.

I am also using Telerik's OpenAccess ORM, but I don't think that should be causing any problems here?

EDIT:

Turns out this was an issue with th Telerik OpenAccess ORM, which under certain conditions would just give up on producing sensible SQL, draw everything into memory and treat it as L2Objects (which should fail on nulls, as pointed out by @Dead.Rabit). The condition that seemed at least part of the problem was the .Where(o => o.Type == "BasicGroup") in front of the .DefaultIfEmpty(). Updating to the latest version of OpenAccess (2013 Q1 SPI I think it was) allows me to rewrite that condition as part of the equals statement

on new { objectA.ID, Type = "BasicGroup" } equals new { ID = objectB.AID, Type = object.Type }

This wasn't possible before the SP1. With this new query, I am able to compose the searchword Where clauses into the query and still have it produce SQL rather than drawing it into memory.

Was it helpful?

Solution

AB can be null since your creating it with DefaultIfEmpty() function, but also if ObjectA.Name can be null; Contains() in your second statement will throw an error. Similarly if ObjectB.ID or ObjectB.Name can be null when ObjectB is not null then your ObjectB != null guard clause won't have the desired effect.

Try a simple enumaration of your objects to ensure the issue is with your first query

foreach( var item in searchObjects )
    Console.WriteLine( item.Type );

Your redefining the searchObjects variable every itteration which I assume is something lost in the code-dump to SO, but worth a mention JIC.

Finally I'm not sure about the OpenAccess ORM since I've never used it, but this query would fail on the Dynamics CRM implementation of LINQ which doesn't support certain types of conditions in where clauses (I won't go into details because it's irrelevant, but you've broken all of them in this query :p). It's definitely worth browsing the documentation for gotcha's in a 3rd party LINQ implementation.

OTHER TIPS

I'm not 100% sure but i think you need to use AB instead of objectB in your anonymous type.

select new { objectA, AB }

because thats the result of the left join.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top