I have an EF context with four Entities in it, SaleGroup, SaleDepartment, SaleText & Tax. Now SaleGroup can have a collection of SaleDepartments, a SaleDepartment can have a Tax and a collection of SalesText.
When I request a collection of SaleGroups from the context I get all child records. However, when I have the Report do this it is only returning the SaleGroups, and no child collections, the SQL profiler confirms this with the TSQL generated.
The Report Designer looks mighty fine, it creates a detail based on SaleGroup and then another detail that is based on SaleGroup.SaleDepartment and another detail that is based on SaleGroup.SaleDepartment.SaleText.
Is what I'm trying to achieve possible, as from the Report Designer it looks likely, or am I going about this totally the wrong way?
I have tried a new report and thrown an object at it, which then works fine at runtime but the preview doesn't, any idea why the preview doesn't or is that just not possible for an object?
Ta.
Hi Ta,
>>I have tried a new report and thrown an object at it
Would you please clarify how you're filing your report with data? Are you using any component for this purpose? Please share the definition of your DBContext and all relevant entities. Based on your description, I imagine we have a situation with the EF's Lazy loading feature disabled. In this case, nested navigation properties won't be loaded unless you include them explicitly to the query with Include().
I look forward to your reply.
Regards,
Yaroslav
Sure,
My context is simply
public class MyContextFoo : DbContext { public MyContextFoo() : base("name=myappname") { Database.Log = p => Write(p); } public DbSet<SaleDepartment> SaleDepartment { get; set; } public DbSet<SaleGroup> SaleGroup { get; set; } public DbSet<SaleText> SaleText { get; set; } public DbSet<Tax> Tax { get; set; } }
If within my MainWindow I place the following:
var foo = new MyContextFoo().SaleGroup.Include("SaleDepartments.SaleTexts").Include("SaleDepartments.Tax").ToList();
I get everything I require with Foo. However, the report has an DataSource of efDataSource1, and the DataMember of SaleGroup, which when I go to change this gives me the following image:
So it knows what to bring in, and the report layout is exactly what I'm after, but it's just not bringing in any children :(
Colin.
BTW. Ta is short for Thanks in the UK ;)
Looks like the images I pasted didn't work, here's the data member one.
And here's the report layout one.
>>However, the report has an DataSource of efDataSource1, and the DataMember of SaleGroup, which when I go to change this gives me the following image:
Are you saying that you're getting an error message about the wrong / missing DataMember? If that is correct, you actually need to wrap 'foo' into a fake class with one "SaleDepartment" collection property (to the match the exact schema against which your report has been designed). Also, I see that you're using our EFDataSource component. Are you saying that if you don't substitute it with a runtime collection, it does not produce any output for nested navigation properties? This behavior is unexpected. Although EFDataSources handles this scenario in not a very effective way (a separate SQL query is sent for each master object), I'd expect to see all data in the preview nevertheless.
>>BTW. Ta is short for Thanks in the UK ;)
Alright, that was awkward, I though it was your name :) Thank for you clarifying this, Colin.
I'm not getting errors as such when using the EFDataSource, I'm just not getting the related child records.
So investigating this further I have decided that I'm probably better using an ObjectDataSource and using my context the retrieve all necessary data from SQL in one swoop and have the Report use the collection returned, and can confirm that this works in the scenario I tried.
One final question based on ObjectDataSource if I may is, the 'actual' data retrieved, if it is coming from a context then I take it the data shown on the preview of the report designer is 'design time data' rather than actual data, which is then returned from a constructor which the report can then call?
Colin.
>>then I take it the data shown on the preview of the report designer is 'design time data' rather than actual data
This depends on how your ObjectDataSource is set up. For example, if you're binding to a method of some static helper class, this method will be called when you switch to the preview tab (meaning you'll see all the expected live data there). At design time, the schema that you see in the Field List window will be obtained by the means of Reflection. To see what possible ObjectDataSource configurations exist, see How to create Data Access Library data sources at runtime
P.S. Don't try to preview live data right in the Visual Studio Report Designer, as this won't work. While EFDataSource does a lot of heavy lifting to instantiate DBContext at design time, there is nothing similar for ObjectDataSource. As for EFDataSource, do you think it will be possible to create a small demo for us illustrating the issue? Although I understand that you have a working workaround, I'm still concerned why it doesn't fetch related navigation properties as it's supposed to.
Thank you for your time and cooperation in advance.
Regards,
Yaroslav
Please see the attachment, I have reproduced it in a sample app with sample database attached as well (You'll have to add the entity framework 6.2 nuget to make it work). You'll will probably need to update the connection string. You'll notice that there is one SaleGroup with two SaleDepartments and one of the SaleDepartments has a couple of SaleTexts, but when you run it only the SaleGroup will show.