ComponentOne DataSource™ for Entity Framework adds ease-of-use and performance enhancements to the Microsoft Entity Framework. It simplifies data binding with its super-easy, design-time capabilities. It also improves application performance with its data caching and data virtualization mode for navigating infinitely large data sets asynchronously. In this blog post I will walk you through getting started using the Entity Framework and the C1DataSource component in WPF. Here's an overview of this post:
- Creating an Entity Data Model
- Using C1DataSource:
- Data binding to FlexGrid
- Enabling auto-lookup comboboxes
- Server-side filtering
- Enabling data virtualization (Virtual Mode)
- Saving changes
- Configuring live views (master-detail)
Creating an Entity Data Model
The Entity Framework is an object-relational mapper that enables you to work with relational databases using classes in your .NET application. It eliminates the need for most of the data-access code that you typically need to write by allowing you to configure most features through the designer. There are three workflows that you can use to get started using the Entity Framework.
- Database First – which will generate a model from an existing database.
- Model First – which allows you to create a new database using boxes and lines to create a model.
- Code First – allows you to define a new data base, or map to an existing one, from code.
In this post we will use the database first workflow in a new .NET 4.5 WPF Application. Once you have your project, add a new ADO.NET Entity Data Model. This model will provide the data for the entire application. In this demo, I’ll use the AdventureWorks database so I’ll name my model AdventureModel.edmx.
Using the Database first workflow, I will generate the model from an existing database. If you were to use Model First, you would start with an empty model.
On the next page is where you will select or create the connection string to your database. This is a standard process we’ve all seen before. At the bottom we give a name to our entities collection. As you can see I’ve already configured this to connect to SQL Express and my AdventureWorks database.
On the next page, choose the Entity Framework version 6.0 and click Next. This the minimum version supported by the C1DataSource control when using ContextType.
On the next page select the tables and views to include in your data model. I will include all of the sales tables.
When you click OK, Visual Studio will then generate the model. You may see a warning that it’s running a text template, on which you should allow it to run. Now that you have a model, you could further modify the mapping and the shape of the classes in the designer.
Next, you should go ahead and build your project so that all of the necessary classes get built so they are exposed to controls within your application.
Now we are ready to work on the user interface. This is where the C1DataSource component will be used to help connect our UI controls to our entity data model. Locate and drag a C1DataSource component from the toolbox onto the Window. This is a non-visual component, so you can put it anywhere behind your other UI controls. You need to give it a name so we can later bind controls to it. For example, name it OrdersDataSource. To connect it to our entities, just set the ContextType property to the entities collection you wish to use. In my case I will see an option for the AdventureWorks entities I just generated.
At this point, the C1DataSource will create an object that represents my AdventureWorks data and it will have complete application scope. If I had additional Windows or User Controls with other instances of C1DataSources, they will share the same object so long as they point to the same context type. This unified Entity Data Cache object is one of the main advantages of C1DataSource. Without it, you would have to create and synchronize multiple object contexts throughout your application. Next, you need to specify the entity sets C1DataSource will expose to the application by modifying its ViewSource collection. Open the ViewSourceCollection and click Add to add an Entity View Source. For each source you add here, you should specify the EntitySetName from the ones defined in your model. In this case, I will select SalesOrderHeaders for the first entity.
We can close that and now let’s add a grid control to view our data. You can use C1DataSource with any UI control, such as a ComboBox, a C1DataGrid or the C1FlexGrid control.
Data Binding to C1FlexGrid
I will bind a C1FlexGrid control to my C1DataSource. To connect the control you need to bind its ItemsSource property to the C1DataSource component. You can do this by setting the ElementName and then set the Path to the data member name. In my sample, the Path will be set to SalesOrderHeaders. At run-time, we can confirm the data is loaded from the existing database. And now that we’ve accomplished this using the Entity Framework and the C1DataSource, we can begin to unlock more features very easily.
Enabling Auto-Lookup Comboboxes
You may notice in your data set that you have several columns that don’t display readable information. The first feature you will want to use is the Auto-Lookup feature. Using the relationships in your data model, C1DataSource can automatically configure grid columns to display look-up comboboxes for referenced navigation properties. To enable this, add a C1DataSource Control Handler to the FlexGrid control. On the ControlHandler, set the AutoLookup property to True.
Now when we run this, we’ll see that columns of referenced look-up objects will display as a combobox. For instance, the territory column now displays readable information. There are rules here that if the entity class does not override the ToString method, or contain a property like Name or Description, then no lookup is automatically created. You can find more information on this feature in the documentation. Another common scenario is that we may only want to bring a subsection of the data down to the client. For instance, our database may contain date information as far back as 12 years and we may only be interested in the current year. C1DataSource has a server side filter feature that makes this task very easy to accomplish without writing any code. From the view source collection editor, open the FilterDescriptors and one or more filters. For example, I will filter out all values before 2008. Using the same approach you can add sorting descriptors as well by adding to the SortDescriptors collection. We can verify at run-time that a much smaller subset of our data has been loaded. The filtering has been performed on the server so we’ve only brought down the necessary records. Using this feature you can greatly improve the initial load times of your grids without having to write any code or SQL script.
Enabling Data Virtualization (Virtual Mode)
In addition to the server-side filtering, C1DataSource provides other solutions for handling large data such as paging, and data virtualization with our innovative Virtual Mode technology. With these solutions, data is fetched from the server in chunks. The benefit of virtual mode over paging, is that this retrieval is completely transparent to the user AND the developer. To turn on virtual mode, you need to set the VirtualMode property on the view source to Managed which means the fetching will be managed by a UI control. Then you need to also set the VirtualMode on the Controlhandler on the FlexGrid to true. By setting these two properties we’ve now enabled complete server-side data virtualization. With Virtual mode there is no limit to the amount of data, your app will only load the number of records needed by the UI. The FlexGrid is aware of the full size of the data so the scroll bar makes it look like all data has been loaded, but really data is being fetched in chunks when we stop scrolling. You can even still sort and filter the data as you normally would, as those actions are performed on the server.
Next, let’s consider saving data. When you edit the data, it’s not saved back to the database automatically. For this you must write one line of code. For instance, In the FlexGrid’s CellEditEnded event, you can call the C1DataSource’s SaveChanges method which will submit all changes to the server. Where you put the call to save is up to you, as you may prefer to do a batch save to limit the number of calls to the server.
Configuring Live Views (Master-Detail)
Let’s consider one more scenario, creating master-detail bound grids without writing a single line of code. One of the major benefits to C1DataSource is its live views capabilities. The data model classes that are generated using the EF 6.0 generator unfortunately do not support live collections of data (ie, they do not implement INotifyPropertyChanged or use ObservableCollections). This means updates to the data are not automatically reflected on the UI as is required with master-detail scenarios, live views with LiveLinq, or if you’re doing MVVM. When you installed Studio for WPF, we installed a text transformation template that can be used to generate classes that support live data. Simply find and delete the two “tt” text transformation files for your entity data model. Then right-click on the diagram and select “Add Code Generation Item.” Here you should find the ComponentOne EF 6.x DbContext Generator template. Select it and give it the same name as your entity data model. In my case, it’s AdventureModel.tt. Click Add, and once this generates you will notice a few major differences in the new tt files.
- Each class now implements the INotifyPropertyChanged interface.
- And each collection of objects is now an ObservableCollection.
These are the two key ingredients to supporting live views. Now we can set up our form to display master-detail grids. Open up the ViewSources collection and set the Include property on our SalesOrderHeaders view to include the related SalesOrderDetails entity set. The Include property is a comma-separated list so you can include multiple child collections. Click OK. And then, add another FlexGrid, this one bound to the SalesOrderDetails. The key thing to get correct here is the Binding Path. Since SalesOrderDetails is included with the headers, we need to denote it like this: SalesOrderHeaders forward slash SalesOrderDetails. Here's the ItemsSource Binding for the 2nd, child grid: And just like that, we have a live, bound master-detail form without writing a single line of code. As you select rows from the master grid, the details grid automatically populates with its details. That completes the getting started tutorial for ComponentOne DataSource for Entity Framework in WPF. You’ll find discover more in-depth information in our online documentation, samples and blogs which go a bit deeper into the Entity Framework and C1DataSource. Get started by downloading Studio for WPF.