Thursday, 30 June 2011

EF4.1 Entity Framework Bind Issue with GridView

I've had an odd issue with Entity Framework 4.1 EF4.1 when binding to a GridView when adding a new items with a Repository using a Unit of Work pattern.

Symptoms are

  1. Add new item to Repository
  2. Save
  3. Refresh the GridView with the new item
  4. GridView Can not bind due to a "Object Does not match target type" exception
The thing it is does match and it should be perfectly acceptable.  Digging Deep this is what I found:

Click to enlarge
The new object added is of a different type to other stored objects already in the database. But they all come from the same place and should all be the same object.

But making a small change to the Repository Helper Code fixes this.

So Adding a specific cast for the fetch from the repository seems to work and it will bind to the GridView with no issues.  If we look again at the collection just before it binds to the GridView then we see that it is all the same object type.

Click to Enlarge
The above work around does NOT WORK in all cases. See other suggestions below.

Further Investigations: 

The above solution did seem to work for while but it simply failed on another section of code that has new items added to the Entity. This is because the GridView control can't deal with polymorphic data sources when using BoundFields.  

The two alternatives are 

1.  GridView : Template Fields

Use TemplateFields on GridView instead of BoundFields.  TemplateFields can deal with polymorphic datasources. If howevert you have a lot of code already written you may have to change front end code if you use row commands etc.

2. Use Linq for DataSources for transitional sourvce.

So instead using the incoming polymorphic collection from EF simply use Linq to extract what you need.

        protected void GetAllProducts()
            gvGroups.DataSource = ProductHelper.Get();

You can create a Linq query that will create an object collection that is not polymorphic as below.

        protected void GetAllProducts()
            var query = from p in ProductHelper.Get()
                        select new {p.ProductId, p.ProductName, p.ProductDesc, p.ProductLink};

            gvGroups.DataSource = query;

The real issue here is how the GridView control handles incoming data, I did as other have done and go sidetracked thinking the problem is with Entity Framework and the returning object set.

Other Solutions

I've seen some crazy stuff to get passed this issue such using cloning or translational interfaces with various code that changes the collection coming in. This is far too complex and defeats the purpose of using EF in the first place which allows for model changes with minimum code changes. I will be using a mix of Linq and Templates where I think the best will suit.

No comments:

Post a Comment

Comments are welcome, but are moderated and may take a wee while before shown.