Diego Vega

Entity Framework news and sporadic epiphanies

May, 2008

Posts
  • Diego Vega

    EntityDataSource: To wrap or not to wrap

    • 6 Comments

    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.

  • Diego Vega

    New EntityDataSource Control for ASP.NET

    • 3 Comments

    As it was announced today, the EntityDataSource is now part of Entity Framework, and a first beta version of it is available in .NET 3.5 SP1 Beta 1 and Visual Studio SP1 Beta 1.

    I have meant to answer Julie's post "Thinking about the EntityDataSource" for several months. But I always thought it was risky to talk about stuff that hadn't been released.

    Now that customers can actually smell and touch it, it is about time:

    Some history and acknowledgments

    EntityDataSource was developed by a small subset of the Entity Framework Team in less than nine months, which is a short period for most software projects at Microsoft. It is amazing to see what this small team has produced.

    But bringing it to its current state would have not been possible without the help of several members the ASP.NET team, who were always helpful and devoted their time and knowledge to the project. They helped us not only in making it suit the needs of “classic” ASP.NET developers, but also of ASP.NET Dynamic Data.

    Why a new DataSource?

    You may have already learned that LinqDataSource is an excellent alternative for displaying the results of any LINQ query (including LINQ to Entities) in ASP.NET, although, to update the database, you need a LINQ to SQL backend. Also, it is possible to write some code and get ObjectDataSource perform 2-way databinding against Entity Framework classes, but that dilutes one of the design goals for DataSources, that it should be possible to implement most common scenarios in a declarative only fashion.

    Entity Framework includes a text based query language called EntitySQL, which in v1 is the only way to get access to the full query capabilities of EF. The language is very “composable”, which enables us to create queries using builder methods (similar to LINQ sequence operators, but text based). On the other side, DataSources as all ASP.NET controls can be initialized using string properties in markup.

    It is easy to conclude that using EntitySQL, it should be possible to create a DataSource control that does 2-way databinding using only markup.

    In fact, this simple markup produces a fully functional CRUD form for the Customers EntitySet:

        <asp:DetailsView ID="CustomerDetailsView"
            runat="server"

            AllowPaging
    ="True"
            AutoGenerateRows="True"
            DataKeyNames="CustomerID"
            DataSourceID="CustomersDataSource">
        </asp:DetailsView>
        <asp:EntityDataSource ID="CustomersDataSource"    
            runat
    ="server"

            ConnectionString
    ="name=NorthwindEntities"
            DefaultContainerName="NorthwindEntities"
            EnableDelete="True"
            EnableInsert="True"
            EnableUpdate="True"
            EntitySetName="Customers">
        </asp:EntityDataSource>

    More to follow...

  • Diego Vega

    Lazy loading in Entity Framework

    • 1 Comments

    Recently, I wrote this little article that got published in the new Insights sidebar in MSDN Magazine. In it, I mention one of the fundamental tenets of ADO.NET: 

    *Network roundtrips should not be hidden from the developer*

    But guess what... It is not always the case that there is a network (or even a process boundary) between your application and your database. Also, there are many scenarios in which you know that most of your data seldom changes or that you don't care if things changes a bit while your application is running (think of a cache). In those circumstances, implicit lazy loading just makes sense.

    We have been sending out the message that you can get implicit lazy loading by changing the standard code generation process in Entity Framework.

    My colleague Jarek went far further and created an experimental set of entity classes that completely replaces the default code-generated classes in EF. And his implementation actually includes some very cool ideas that go beyond lazy loading.

    Take a look at his post. And you can find the bits (compatible with the just released Visual Studio 2008 SP1 Beta) from our portal in Code Gallery.

    Update: Just wanted to add some relevant links to customers asking for lazing loading in EF:

  • Diego Vega

    Entity Framework Extensions Project Update

    • 0 Comments

    Just a couple of links:

    Colin posted a refresh today today that is compatible with .NET 3.5 SP1 Beta and includes some optimizations for the materializer using dynamic methods. Here is his post about it.

  • Diego Vega

    EntityDataSource's flattening of complex type properties

    • 0 Comments

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

    Julie asked for some details today in the forums. I think the answer is worth of a blog post.

    In ASP.NET there are different ways of specifying which property a databound control binds to: Eval() Bind(), BoundField.DataField, ListControl.DataTextField, etc. In general, they behave differently.

    The flattening we did on EntityDataSource is an attempt to make the properties that are exposed by EDM entities available for 2-way databinding in most of those cases.

    For instance, for a customer that has a complex property of type Address, we provide a property descriptor for customer.Address, and also for customer.Address.Street, customer.Address.Number, etc.

    At runtime, in the case of a control binding to Eval(“Address.Street”) from a customer, Eval will use the property descriptor corresponding to Address, and it will drill down on it to extract the value of the Street property on it.

    A grid column of a BoundField derived type with DataField = “Address.Street” will work differently: it will just look for a property descriptor in the data item with a name as “Address.Street”. In fact, EntityDataSource is the first DataSource control that I know off that will provide such a thing.

    Bind(“Address.Street”) will work in a similar fashion to Eval() when reading the properties into the data bound control, but will act a little bit more like BoundField when sending back changes to the DataSource.

    There are a few cases in which the behavior is not any of the above and hence you end up with a control that cannot have access to a complex type’s properties. You can expect us to work closely with the ASP.NET team in making the experience smoother in future versions. But for the time being, what you can do is create an explicit projection of the properties. For instance, in Entity SQL:

           SELECT c.ContactId, c.Address.Street AS Street 
     
         FROM   Northwind.Customers AS c

    I think it is worthy of mentioning:

    • Remember flattening of complex properties only happen under certain conditions (see wrapping).
    • We worked very closely with the ASP.NET Dynamic Data in this release, to enable their technology to work EDM through the EntityDataSource. I think it is very worthy of trying.

    Hope this helps.

Page 1 of 1 (5 items)