views:

52

answers:

2

Suppose we have 2 types, mapped to a Database via EF 4.

Schedule 1.....1 Visit

Also, we have third custom view type

public class ScheduleView
{
    public Schedule Schedule { get; set; }
    public Visit Visit { get; set; }
}

So we can write the join query

var query = Context.Schedule.Join(Context.Visit
,/*Schedule join key definition*/,/*Visit join key definition*/,
(scheduleView, visit) => new ScheduleView {Schedule = scheduleView, Visit = visit})

The problem is that I need to load also Patient property of Visit type. But when I write

query = (query as ObjectQuery<ScheduleView>).Include("Visit.Patient");

I receive a runtime error

Unable to cast the type 'System.Linq.IQueryable1' to type 'System.Data.Objects.ObjectQuery1'. LINQ to Entities only supports casting Entity Data Model primitive types.

So, the question is - how to force query to include something within my custom type?

+1  A: 

The error is spot on. Your trying to create an ObjectQuery (LINQ-Entities IQueryable), with a type (ScheduleView) which does not exist in your Model.

You can project into this type, sure - but not affect the query with it.

Will something like this work? (off the top of my head, untested)

var scheduleViews = (from s in ctx.Schedules
                     join v in ctx.Visits.Include("Patient") 
                     on v.ScheduleId equals s.ScheduleId
                     select new ScheduleView 
                     { 
                        Schedule = s, 
                        Visit = v 
                     }).ToList();

Your main problem is ObjectQuery<ScheduleView> is not translatable to a store expression. So do your include on the Visits entity set, not the IQueryable.

HTH

RPM1984
It doesnt work - looks like the information about Include on Visit type is lost as soon as the result query deals with other type. So Im still stuck with it.
When you say it doesn't work. Does it compile? Does it give a runtime error? Also - are you using standard EF code gen, or using some sort of custom (ie POCO's)
RPM1984
It compiles, it runs, but ScheduleView.Visit.Patient is null. I'm using STE standart generator. So, when I load directly like ctx.Visits.Include("Patient").ToList() I get my Patient property loaded properly.
that was my next question. :) (did you try and get Visit/Patient directly). Damn. Okay, so couple of things: 1) i assume in your EF Model, you have an entity called "Visit", with a Navigational Property called "Patient"? 2) try projecting to an anonymous type instead (`select new {` instead of `select new ScheduleView`). 3) did you try running SQL profiler in the background? See if the JOIN is happening correctly.
RPM1984
Also, i have never needed to use explicit joins, i use the navigational properties on the model. Shouldn't `Schedule` entity have a navigational property called `Visit`, and `Visit` entity have a navigational property called `Patient`? If so, can't you do `var foo = ctx.Schedules.Include("Patient").Include("Patient.Visit").ToList()` ? Are you using navigational properties? maybe can you screenshot your EDMX?
RPM1984
Schedule doesnt have neither Visit nor Patient properties, they are not connected directly. Considering changin to anonymous type - it doesnt work also. I've Traced SQL - it's ok, but it doesnt query Patient Table at all :( –
They're not connected? So you have no FK's/Nav Props? AFAIK `Include` causes a LOJ on a given nav property. So if you don't have a "Visit" nav property, it won't work (surprised it works directly). Try left outer joining explicitly to "Visit" from "Patient" isntead of include. Really though, you should have FK's and Nav Props.
RPM1984
Looks like I've explained it wrong. Schedule and Visit are not connected via any Nav props. I join them basing on some business logic and create an aggregate type - ScheduleView. Visit type has nav property Patient and I want to load this property in the same query. But Include doesnt work on Visit type as I showed earlier.
A: 

Finally, developed some ugly workaround - introduced new member in custom type and explicitly queried for it.

public class ScheduleView
{
    public Schedule Schedule { get; set; }
    public Visit Visit { get; set; }
    **public Patient Patient{ get; set; }**
}

    var query = Context.Schedule.Join(Context.Visit
    ,/*Schedule join key definition*/,/*Visit join key definition*/,
    (scheduleView, visit) => new ScheduleView 
{Schedule = scheduleView, Visit = visit, **Patient = visit.Patient**})

Now I have Patient loading properly in my custom type. Amusing, but when I investigate ScheduleView.Visiting.Patient after introducing ScheduleView.Patient I found it also loaded. Cant get the EF logic in this case. And dunno how to force loading ScheduleView.Visiting.Patient without having to load useless ScheduleView.Patient :(

enter code here