EntityDataSource: To wrap or not to wrap

Note: Somehow the <TEntity> generic argument had disappeared from the extension method definition. I am fixing it today after several months. Sorry for the inconvenience!

Fresh from the forums today: A customer asks how to get the real entity object in the RowDataBound event of a GridView.

We made some complex design decisions during the development of the EntityDataSource, and I guess that will give us plenty of material for blogging 🙂

With the EntityDataSource, we faced the interesting problem of building a bridge between the existing ASP.NET databinding infrastructure and the world of EDM. One of the techniques we use to solve the problem is wrapping entities in smart databinding objects. As Colin explains it in his answer posted to the forums:

Why are you seeing a wrapper instead of the entity? Some of the unique features of the Entity Data Model prevent us from directly binding the entity. For instance, when inserting a Product I also need to insert a relationship to a Category. The wrapper adds the relationship to the entity, basically as a foreign key value.

The wrapper object implements the ICustomTypeDescriptor interface, which makes it work well with databinding, but when you try to get your original entity object, for instance form the arguments of the RowDataBound, you will get a wrapper object instead of the entity object you are expecting.

I don't want to make things much more complicated than they need to be, but I think the generic solution may be useful for some customers.

First of all, here are the rules for wrapping:

  • The wrapping mechanism only takes place if you initialize your EntityDataSource using EntitySetName.

  • When you instead set CommandText to a query that returns entities (i.e. "SELECT VALUE c FROM Northwind.Customers AS c", then you get normal entities.

  • When you instead set CommandText to a query that returns a projection of properties (i.e. "SELECT c.CustomerID, c.CustomerName FROM Northwind.Customers AS c"), then you get a DbDataRecord.

  • Finally, if you set the Select property to do a projection (i.e. "it.CustomerID, it.CustomerName", you get DbDataRecord regardless of how you start your query.

If you use the RowDataBound event very often in your code, then, I would suggest having around some code similar to this (thanks David for coming up with this code first):

static class EntityDataSourceExtensions


    public static TEntity GetItemObject<TEntity>(object dataItem)

        where TEntity : class


        var entity = dataItem as TEntity;

        if (entity != null)


            return entity;


        var td = dataItem as ICustomTypeDescriptor;

        if (td != null)


            return (TEntity)td.GetPropertyOwner(null);


        return null;



And this is the usage:

protected void GridView_RowDataBound(object sender, GridViewRowEventArgs e)


   var entity = EntityDataSourceExtensions.GetItemObject<Product>(e.Row.DataItem);




I hope this will help some.

Comments (7)
  1. Hot Topics says:

    Lots to read and download from the Data Programmability Team &#160; SP1 Beta Download, what&#39;s new

  2. Diego Vega says:

    I explained a few day ago the rules of wrapping in this blog post . But why do we wrap after all? Julie

  3. Pedro Brown says:

    Why not expose WrappedEntity of EntityDataSourceWrapper as public?


  4. Diego Vega says:

    Hello Pedro,

    Besides the ICustomTypeDescriptor interface, there is nothing very interesting in EntityDataSourceWrapper.

    Can you please describe when you need the type to be public?



  5. Diego Vega says:

    This post is about a small issue that I have seen in the forums and that arises often in cases in which

  6. Thank you!  This helped a lot!

  7. V. Jenks says:

    This simply does not work for me.  I get the same exception as if I were to attempt to directly cast the DataItem of the row as the entity type that is bound to it.

    At this line in your work-around method:

    return (TEntity)td.GetPropertyOwner(null);

    …I get this exception:

    "Unable to cast object of type ‘System.Data.Objects.MaterializedDataRecord’ to type ‘MyData.Model.NewsItem’."

    My event handler looks like this:

    protected void NewsItemsGridView_RowDataBound(object sender, GridViewRowEventArgs e)


    if (e.Row.RowType == DataControlRowType.DataRow)


    NewsItem ni = EntityDataSourceExtensions.GetItemObject<NewsItem>(e.Row.DataItem);

    e.Row.Cells[3].Text = ni.dateReleased.ToShortDateString();



Comments are closed.

Skip to main content