Sunday, August 03, 2008

Drag-and-Drop Master/Details Windows Forms Still Missing from Entity Framework SP1 Beta

LINQ to SQL Master/Details Form Generated by Dragging Entities and EntitySets

Updated 8/3/2008: “What’s Needed from the EF Team in Addition to Exposing EntityReference<T> and EntityCollection<T> As Data Source Nodes” topic added at end.

LINQ to SQL has supported drag-and-drop generation of master/details and master/details/subdetails forms from the Data Sources window since its first appearance in an early Orcas beta release. Although this approach to rapid application development (RAD) of data-intensive applications is best suited to demos at technical conferences, there are many production and administrative scenarios that can take advantage of Windows application designs similar to Figure 1:

Figure 1. An example of a LINQ to SQL master/details/subdetails Windows application created by dragging-and-dropping from the Data Sources window.

As is evident in the preceding screen capture, LINQ to SQL surfaces foreign key values, such as Order.CustomerID, Order.EmployeeID, and Order.ShipVia (not visible.) The Orders DataGridView has Customer, Employee, and Shipper columns that display type information (Application.EntityType) for many:one EntityRefs, which are hidden from the user but accessible from the BindingSource.Current property value.

Limitations in Entity Framework’s Drag-and-Drop Implementation

The version of Entity Framework (EF) v1 in the Visual Studio 2008 SP1 Beta release can drag-and-drop TextBox or DataGridView icons from the Data Sources window to the form in design mode, but the Data Source nodes don’t include EntityReferences, such as Order.Employee and Order.Shipper, or EntityCollections, such as Customer.Orders or Order.Order_Details. Neither does the current EF v1 release display foreign key values unless they’re part of a primary key, such as Order_Detail.OrderID and Order_Detail.ProductID, as is evident in Figure 2:

Figure 2. An example of an Entity Framework master/details/subdetails Windows application created with the same process as Figure 1. 

Natural keys are primary keys that supply meaningful values to their corresponding entity properties; surrogate keys, such as GUIDs or arbitrary auto-incrementing integers, have no relationship with an entity instance other that its identity and navigation. I requested that EF provide optional visibility of foreign key values as item #9 in my Defining the Direction of LINQ to Entities/EDM post of May 29, 2007 to which EF architect Michael Pizzo replied in a comment:

9. Provide read-only access to foreign key values.

This is actually a feature I’m fighting to get into our final milestone for V1. Can you describe the scenarios where this is used? Do you need the ability to query on the foreign key value, or simply expose it on the domain object?

I described the scenario to Mike as emulating LINQ to SQL’s autogenerated databound grids, which let you change EntityRef foreign key values that aren’t a component of the object’s EntityKey, such as Order.Employee and Order.ShipVia.

EF development lead Danny Simmons said in his reply to a question regarding EF databinding in the ADO.NET Entity Framework and LINQ to Entities (Pre-release) forum’s Re: BrowsableAttribute for certain properties / no properties for foreign keys thread started December 28, 2007:

It is our intention to support this kind of model for asp.net data binding using the entity data source control which should be available by EF v1 RTM.  We don't currently have plans to support this for winforms/wpf data binding in the first release, though.  We'll work on ways to simplify this kind of pattern in future releases.

It appeared at this point that Mike had lost the fight.

Subsequent EF Navigation Property Developments Post-Beta 3

The EF team’s Diego Vega said on May 2, 2008 at the end of Re: DataMember not visible when using BindingSource connected to Entity Framework Beta3 thread:

[T]he reality up to beta 3 was that Entity Framework binding lists would not expose navigation properties for one-to-many or many-to-many relationships for databinding.

In more recent bits, we incorporated several improvements to our databinding story. In the final release of EF v1, you should be able to implement the master-detail scenario you describe without writing any code to synchronize both DataBound controls.

Also, we implemented the necessary interfaces for drill-down capabilities.

In the meanwhile, I can tell you that the mechanism that was used in beta 3 to hide collection navigation properties was based in a [Browsable(false)] attribute we placed in those properties in the code-gen classes.

Removing that attribute causes the databinding list to start exposing the collection property, but unfortunately this is not a good workaround, since the whole code-gen class is overwritten every time you change your Entity Data Model. [Emphasis added.]

The two points at which navigation properties might have been exposed, “up to beta 3” or after beta 3 (“was used in beta 3”), or after SP1 Beta (“final release of EF v1”). Microsoft released VS 2003 SP1 Beta on May 12, 2008.

However, it turns out that data binding didn’t get fixed in SP1. Diego Vega says in his Re: Databinding on navigation Properties post of July 25, 2008:

After SP1 beta we improved a lot of things around databinding. Among them, we removed the Browsable(false) attribute from navigation properties, and we got teams in Visual Studio and WinForms to change things a little bit so that databinding to nested EntityCollection<T> actually works both in design-time and runtime.

As a result, in a WinForms application in recent builds, you can just drag and drop Customers and Customers.Orders from the Data Sources window, then write a couple of lines of code that look like this (from the top of my mind, sorry if it does not compile):

protected NorthwindEntities contex = new NorthwindEntities()
protected void Form_Load(object sender, EventArgs e)
{
    bindingSource.DataSource = context.Customers.Include(Orders);
}
And you get a very simple master-detail scenario running. [Emphasis added.]

I haven’t heard anything about a VS 2008 SP1 Beta 2 or RC1, so it appears to me that EF v1 data binding for WinForms will arrive at RTM with no external testing.

What’s Needed from the EF Team in Addition to Exposing EntityReference<T> and EntityCollection<T> As Data Source Nodes

Hopefully, the testers will put EF databinding through the paces with multi-level DataGridView controls with bound ComboBox cells such as that shown in Figure 3. I’m finding some strange behavior with LINQ to SQL and ComboBoxColumns that doesn’t occur with DataSets as the data source.

Figure 3: The form of Figure 1 with data-bound ComboBoxColumns added and unnecessary CustomerID column removed from the detail DataGridView.

Fulfilling Diego’s promise that developers using Entity Framework v1 “can just drag and drop Customers and Customers.Orders from the Data Sources window, then write a couple of lines of code” that enable nested EntityCollection<T> associations to populate detail grids isn’t enough. We’ll also need sample code at RTM to:

  1. Display scalar primary key property values from EntityReference<T> associations (such as Order.Customer.CustomerID, Order.Employee.EmployeeID, and Order.Shipper.ShipperID) as editable TextBoxColumn values to emulate LINQ to SQL’s default foreign key value.
  2. Display meaningful scalar property values from EntityReference<T> associations (such as Order.Customer.CompanyName, Order.Employee.LastName, and Order.Shipper.CompanyName) as read-only TextBoxColumn values to emulate tje default Order grid display of ASP.NET Dynamic Data (DD).
  3. Enable updating EntityReference<T> associations with ComboBoxColumns as shown for the SalesPerson and ShipVia columns of the Order DataGridView (DGV) and ProductName column of the Order_Details DGV to emulate DD’s Edit page for Order entities. Deleting and recreating an entity to update an EntityReference<T> isn’t acceptable for entities, such as Order, which have an autoincrementing primary key. 
  4. Display read-only foreign key values in unbound cells without requiring user action (such as clicking in the cell), as shown for the Order_Details DGV’s SKU column.
  5. Update bound entity property values when changing a related value, such as replacing the Order_Details DGV’s UnitPrice value when changing a Product association.

If EF v2’s POCO entities can’t build in the preceding features or provide them in a VS 2008 add-in, CTP and beta drops should provide the preceding sample code elements for testers.

If EF v1 can’t accomplish the preceding five tasks with added code, in the spirit of “transparent development” the EF team should advise potential EF users of specific limitations as soon as possible.

2 comments:

Ewald said...

hi,
I just started using VS2008 SP1 and I tried to create a datagridview with comboboxes according to your example 3 (I am using entity data model created with VS2008 SP1designer). But comboboxes in datagridview won't work in my solution (it seems that the Navigation Property referenced in DataPropertyName of the datagridview column causes the problem). Should comboboxes (in datagridview) work in conjunction with entity data model in VS2008 SP1?
regards
EWald

--rj said...

@Ewald,

I've found problems with combo boxes bound to BindingSources when the DataSource of the BindingSource is an EntityCollection (1:many navigation property.)

If I change the binding to an EntitySet (e.g., Northwind Orders) and manage its scope with code, combo boxes behave as expected.

A symptom of the problem is the lack of visible DataMember property value(s) when binding the BindingSource to an EntityCollection data source.