When upgrading to use Entity Framework we are also in the process of trying to change all appropriate business layer calls to IQueryable – the main point of which was so that our UI can define specific projections on the data as it needs. Unfortunately we found no way that we could attach to a BL using some kind of DataSource and have this projection capability. So this post is out to create one.
The steps required to make this work are the following in my mind:
- Extend the currently existing ObjectDataSource to provide hooks for IQueryable returns.
- Extend controls you want to project so that they return which fields they need in a consistent manner.
- Create a ‘Selector’ control that is separate from the ObjectDataSource that handles the actual dynamic projection.
- It is also possible to do Inserts/Updates/Deletes back from the original control if it supports it.
At the end of this series I’d be hoping to get something like this going:
Business Layer Class
public class BLClass : IDisposable
{
public IQueryable<Topic> FindAll()
{
return Entities.Topics.Where(t => t.SortedMetadata.IsActive);
}
}
UI
<psuc:ComboBox ID="ComboBox" runat="server" DataSourceID="Source" DataTextField="Name" DataValueField="TopicId" />
<psuc:Grid ID="Grid" runat="server" DataSourceID="Source2"
AutoGenerateColumns="False">
<MasterTableView DataKeyNames="TopicId">
<Columns>
<telerik:GridBoundColumn HeaderText="Id" UniqueName="Id" DataField="SchoolId" />
<telerik:GridBoundColumn HeaderText="Name" UniqueName="Name" DataField="Name" />
</Columns>
</MasterTableView>
</psuc:Grid>
<psuc:QueryObjectDataSource ID="Source" runat="server" SelectMethod="FindAll" TypeName="TelerikTest.BLClass" />
<psuc:Selector ID="Selector" runat="server" DataSourceId="Source" ControlId="ComboBox" AdditionalFields="SortedMetadata.Name" />
<psuc:QueryObjectDataSource ID="Source2" runat="server" SelectMethod="FindAll" TypeName="TelerikTest.BLClass" />
<psuc:Selector ID="Selector2" runat="server" DataSourceId="Source2" ControlId="Grid" AdditionalFields="SortedMetadata.Name" />
Here we define a single method in the business layer but in our UI because we have attached the ‘Selector’ to each control we actually find that the ComboBox control query’s for only the “Name” and “TopicId” field (and to be compatible with EF we define in the selector how to get that “Name” field). The Grid control will pull out both the items in the DataKeyNames property but also the properties defined in the bound columns. You could imagine this being extended to any control that uses a list.
Now that I have explained the issue I should quickly point out my focus when coding in the next few blog posts
- We are using EF 4
- The business layer is using POCO entities – with proxies and are also lazy loaded. Lazy Loading is really important for the Update/Insert part of projections – only if you are finding you are flattening out relationships in your model.
In my next post I will talk about extending the ObjectDataSource class to provide IQueryable hooks for the Selector (For selecting only).
Print | posted on Sunday, 22 August 2010 12:49 PM