Alessandro Del Sole's Blog

/* A programming space about Microsoft® .NET® */
posts - 159, comments - 0, trackbacks - 0

My Links

News

Your host

This is me! This space is about Microsoft® .NET® and Microsoft® Visual Basic development. Enjoy! :-)

These postings are provided 'AS IS' for entertainment purposes only with absolutely no warranty expressed or implied and confer no rights.

Microsoft MVP

My MVP Profile

I'm a VB!

Watch my interview in Seattle

My new book on VB 2015!

Pre-order VB 2015 Unleashed Pre-order my new book "Visual Basic 2015 Unleashed". Click for more info!

My new book on LightSwitch!

Visual Studio LightSwitch Unleashed My book "Visual Studio LightSwitch Unleashed" is available. Click the cover!

Your visits

Follow me on Twitter!

CodePlex download Download my open-source projects from CodePlex!

Article Categories

Archives

Post Categories

.NET Framework

Blogroll

Help Authoring

Microsoft & MSDN

Setup & Deployment

Visual Basic 2005/2008/2010

Master-details forms with the ADO.NET Entity Framework

If you are a little bit familiar with LINQ to SQL, you probably already know how simple is creating a basic Windows Forms application for exposing one-to-many relationships between entities via master-detail representations through the UI.

 

In LINQ to SQL this can be accomplished using the Microsoft Visual Studio 2008 automation engine that allow dragging and dropping objects (entities) from the Data Sources window onto the target form. The IDE then adds the needed UI controls, manages the data-binding leaving to us the only job to specify in code the data source regarding the “one” part in the relationship.

 

Unfortunatley this is not available when working with the ADO.NET Entity Framework (introduced by .NET Framework 3.5 Service Pack 1); this means that dragging just the "master" data source onto the form will not automatically bind the "details" as in LINQ-to-SQL, so we need to set this behavior manually.

 

So, how can we accomplish this when working with EF? Another Visual Basic MVP (Ken Tuckerhelped me to find the right way to solve the problem (thanks Ken).

 

Suppose you want to create a Windows Forms application to show tabular data, inside two DataGridView controls, the content of the Categories and Products tables from the Northwind database and that when selecting each category, in the second grid will be automatically bound and shown the related products. 

 

When working with the Entity Framework, we need to recur to the so called eager loading technique that we can realize invoking a method called Include. The following are the first steps required:

 

1.    creating a Windows Forms project with Visual Basic 2008;

2.    establishing a database connection and adding a new Entity Data Model;

3.    adding tables to the EDM (remember to select tables with relationships). In our example we'll add the Categories and Products tables in Northwind;

4.    adding a new data source (Data|Add New Data Source command) pointing to the Categories object that was generated by the mapping.

 

The Data Sources window should look like this:

 

 

 

A this point we can drag the two objects (Categories and Products) onto the form so that Visual Studio can add the appropriate controls to the user interface which should look like this:

 

 

Now we can switch to the Visual Basic code. As we said before, we can't just simply assign the Categories collection (or a LINQ query result for that collection) to the DataSource property of the BindingSource control (CategoriesBindingSource), automatically implemented by Visual Studio, to get the ProductsBindingSource automatically updated for showing details according to the item selected in the first one.

 

According to what we just said, first of all we have to instantiate the EF ObjectContext:

 

    Private NorthwindContext As New NorthwindEntities

 

Once we've done this, we can specify the data source for the “master” part (please refer to the comments below):

 

        'The include method retrieves also related objects

        Dim dataSource = NorthwindContext.Categories.Include("Products")

 

        'The primary data source is always Categories

        CategoriesBindingSource.DataSource = dataSource

 

Then, invoking Include, we can load also the details (eager loading), as shown in the subsequent code:

 

        'The Products' data source is still the CategoriesBindingSource control

        'which contains both Products and Categories...

        ProductsBindingSource.DataSource = CategoriesBindingSource

 

        '...and of this control I can show just the collection I really need

        'assigning to the DataMember property the name of the collection itself

        ProductsBindingSource.DataMember = "Products"

 

Probably this situation puts some limitations: using a string is not a typical LINQ approach, where everything should be strongly typed. Now let's try to run the application. We can just select the rows in the Categories DataGridView to see how the Products one is automatically updated with details:

 

 

 

Obviously this is enough just to show data but some more code should be written if we want to allow the user adding new objects. At this point we must explicitly assign the AllowNew property exposed by the ProductsBindingSource control because, differently from LINQ-to-SQL, in Entity Framework this property is not set as True by default. According to this consideration, we can just specify the following line of code: 

 

        ProductsBindingSource.AllowNew = True

 

But this is not necessary regarding the Categories. Just to make the demo application complete, we can provide the most basic implementation of a method for persisting data to the underlying database. Once enabled the Save button on the BindingNavigator, we can handle its Click event:

 

    Private Sub CategoriesBindingNavigatorSaveItem_Click(ByVal sender As System.Object, _

                ByVal e As System.EventArgs) Handles CategoriesBindingNavigatorSaveItem.Click

 

        Try

            NorthwindContext.SaveChanges()

 

        Catch ex As Exception

 

            MessageBox.Show("An error has occurred while saving changes to the database")

        End Try

    End Sub

 

And that’s all. You can download the source code for this post from this address (MSDN Code Gallery). Inside the zip archive you will find also .vsi installer (created with my Vsi Builder 2008 tool) that will install a reusable code snippet for the Visual Studio 2008 IntelliSense which includes the code related to the master-details data binding task as shown above.

 

Alessandro

Print | posted on martedì 20 gennaio 2009 14:02 | Filed Under [ Visual Basic LINQ/EF/OData ]

Feedback

No comments posted yet.

Post Comment

Title  
Name  
Email
Url
Comment   
Please add 4 and 2 and type the answer here:

Powered by:
Powered By Subtext Powered By ASP.NET