views:

282

answers:

1

I have been searching for way to perform a linq query to get an object graph based on a specific child inheritance type. I may have prased this a little wrong, but I will try to explain.

Lets say I have a EF4 model that has a City entity, a subdivision entity, a house entity and a feature entity. The city has a one to many relationship with subdivision. The subdivision has a one to many relationship to a house. And a house has a one to many relationship with a feature. Two entities subtype the feature entity. Lets call them pool and driveway.

What would the c# linq query be to query the object graphs for all cities that have houses with a feature.OfType "Pool" with city at the root of the graph?

similar to: var cities = from city in context.Cities where ?????? select city

A: 

You need to use the IQueryable.OfType method to restrict which type you are actually interested in working with. The EF4 IQueryable provider will take care of the rest, and generate the proper SQL queries for you.

Queryable.OfType<T>

The following query should work (assuming you have all the proper navigation relationships defined in your model):

var cities = from city in context.Cities
             from house in city.Houses
             from pool in house.Features.OfType<Pool>
             where pool.MaxDepth == 6
             select city;
jrista
Thank you very much. The above query worked well. It did return multiple instances of the same carrier so I added a distint to the end. Do you know how to eager load the graph? I tried to use the .Include("NAVIGATION PATH") like I normally would, but this didn't return any child objects in the graph. var cities = from city in context.Cities.Include("Houses.Features.Pools")...Obviously I am new at this.
Dave W
You almost have it, but you have made one mistake. Pools ARE Features...Features do not have Pools. Your include path would need to be like this: `context.Cities.Include("Houses.Features")`, and that would include all features. The Features property of your House type represents ALL features, ALL the time. You can not selectively populate that collection with only some features...say Pools...at will. You would need to create a Pools property that represents the appropriate kind of relationship to achieve that.
jrista
Jrista - Thanks again for helping out. You certainly clarified how I whould be thinking about/querying the "feature" hierarchy. I did find that even with the recommended change the Include command was not being executed. I did an additional search and came up with this post. Following it resolved the issue. Does seem like a bug or something that the "early" include requests are being lost.http://stackoverflow.com/questions/936558/linq-to-entity-framework-eager-loading-issueRegards,DaveW
Dave W
@DaveW: Just a quick tip on StackOverflow (SO) culture. If someone answers your question acceptably, its customary to vote on the answer, and if it is the correct answer for your problem, accept the answer. This will improve your acceptance rating...you'll want to keep it as close to 100% as you can to keep people answering your questions. ## As for the Include bug, I actually think that one has been around since the EF v1.0 days...its very annoying, and results in some ugly syntax. I am pretty sure they know about it, but they had some more critical issues to resolve first with EF 4.
jrista