none
Why there are two different collections, ObjectSet and EntityCollection, and how to treat them in the same manner using an Extensionmethod

    Question

  • As a newbie (like most of us) on the Entity Framwork I created (visually) a class model. Now I saw there are two kind of collections created, the ObjectSet and the EntityCollection. Can someone explain me why there is a difference and why there isn't just 1 collection class (even the names generated are different, the first one gets the suffix 'Set'). The reason is today I created an extensionmethod which pre-filters a collection before it is further processed. Now because of the 2 collection types I need to create 2 extensionmethods. An example:

    internal static IEnumerable<Specie> ActiveSpecies(this ObjectSet<Specie> species)
    {
        return species.Where(specieLambda => specieLambda.IsActive);
    }

    internal static IEnumerable<Specie> ActiveSpecies(this EntityCollection<Specie> species)
    {
        return species.Where(specieLambda => specieLambda.IsActive);
    }

    Does anyone know if there is a cleaner way to code this?

    Thanks for any help!

    Yours sincerely,

    Evert Wiesenekker

    Tuesday, January 19, 2010 7:54 PM

Answers

  • Hi Evert,

    Although there actually very few similarities between ObjectSet<T> and EntityCollection<T> (i.e. both implement IEnumerable<T>) they are very different and in fact ObjectSet<T> is not a collection type.

    EntityCollection<T> is used to represents a collection of entities related to another entity. For instance, with the default codegen classes, the Category.Products collection ins an EntityCollection<T>. In all cases but those in which you refer to an EntityCollection<T> in a query to perform a query operation over a relationship, EntityCollection<T> is an in-memory collection of objects.

    On the opposite side, ObjectSet<T> provides access to entities that belong to an EntitySet in the database. EntitySets are Entity Data Model equivalent of tables in the relational model. When you use an ObjectSet<T> in your code, it can represents a query object: every time you iterate through it, you are not iterating through a collection that exists in-memory but performing a database server query that will return results. Another use of ObjectSet<T> is to serve as pivot for performing insert, delete and other operations on entities belonging to an EntitySet, but these operations are not equivalent to similar operations on a collection. For instance, when you call context.Products.AddObeject(product), the entity that you pass to it is not going to be available when you iterate over context.Products (i.e. with a foreach statement). It is only after you call SaveChanges that the product will be stored in the database and then it will be returned by the query.

    When you apply LINQ query operators such as where over an EntityCollection<T> the query will be processed by LINQ to Objects. When you apply the same LINQ query operator to ObjectSet<T>, since ObjectSet<T> is an IQueryable<T>, it will use its own LINQ provider, in this case LINQ to Entities to process the query, which will result in the LINQ query to be translated to a database query.

    Also, keep in mind that although both methods in your sample code look the same, there are subtle differences in the signature of the Where operator between the implementation that works over objects of type IEnumerable<T> (in this case EntityCollection<T>) and the version that works with IQueryable<T> (in this case ObjectSet<T>):

    public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)

    public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)

    For the ActiveSpecies method that takes an ObjectSet<T>, I would recommend you to change the signature to return IQueryable<T> or ObjectSet<T> if you want to be able to compose LINQ to Entities queries on top of the call to this method.

    I hope this answers your question,
    Diego


    This posting is provided "AS IS" with no warranties, and confers no rights.
    Thursday, January 21, 2010 7:04 AM
    Moderator
  • What's interesting about ObjectSet is, as soon as you access it and build your query on top of it, you get an objectquery and you no longer have an objectset. One might say why is that? Well at that point it is nothing but a query and not a container that you can attach, add or call DeleteObject which is what an  ObjectSet facilitates. 

    Objectset allows you perform add, attach, delete operation to an entity on a particular entityset.

    Zeeshan
    Thursday, January 21, 2010 7:31 PM
  • Thank you both for demistifying up my question!

    Yours sincerely,

    Evert Wiesenekker
    Friday, January 22, 2010 12:19 PM

All replies

  • Hi Evert,

    Although there actually very few similarities between ObjectSet<T> and EntityCollection<T> (i.e. both implement IEnumerable<T>) they are very different and in fact ObjectSet<T> is not a collection type.

    EntityCollection<T> is used to represents a collection of entities related to another entity. For instance, with the default codegen classes, the Category.Products collection ins an EntityCollection<T>. In all cases but those in which you refer to an EntityCollection<T> in a query to perform a query operation over a relationship, EntityCollection<T> is an in-memory collection of objects.

    On the opposite side, ObjectSet<T> provides access to entities that belong to an EntitySet in the database. EntitySets are Entity Data Model equivalent of tables in the relational model. When you use an ObjectSet<T> in your code, it can represents a query object: every time you iterate through it, you are not iterating through a collection that exists in-memory but performing a database server query that will return results. Another use of ObjectSet<T> is to serve as pivot for performing insert, delete and other operations on entities belonging to an EntitySet, but these operations are not equivalent to similar operations on a collection. For instance, when you call context.Products.AddObeject(product), the entity that you pass to it is not going to be available when you iterate over context.Products (i.e. with a foreach statement). It is only after you call SaveChanges that the product will be stored in the database and then it will be returned by the query.

    When you apply LINQ query operators such as where over an EntityCollection<T> the query will be processed by LINQ to Objects. When you apply the same LINQ query operator to ObjectSet<T>, since ObjectSet<T> is an IQueryable<T>, it will use its own LINQ provider, in this case LINQ to Entities to process the query, which will result in the LINQ query to be translated to a database query.

    Also, keep in mind that although both methods in your sample code look the same, there are subtle differences in the signature of the Where operator between the implementation that works over objects of type IEnumerable<T> (in this case EntityCollection<T>) and the version that works with IQueryable<T> (in this case ObjectSet<T>):

    public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)

    public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)

    For the ActiveSpecies method that takes an ObjectSet<T>, I would recommend you to change the signature to return IQueryable<T> or ObjectSet<T> if you want to be able to compose LINQ to Entities queries on top of the call to this method.

    I hope this answers your question,
    Diego


    This posting is provided "AS IS" with no warranties, and confers no rights.
    Thursday, January 21, 2010 7:04 AM
    Moderator
  • What's interesting about ObjectSet is, as soon as you access it and build your query on top of it, you get an objectquery and you no longer have an objectset. One might say why is that? Well at that point it is nothing but a query and not a container that you can attach, add or call DeleteObject which is what an  ObjectSet facilitates. 

    Objectset allows you perform add, attach, delete operation to an entity on a particular entityset.

    Zeeshan
    Thursday, January 21, 2010 7:31 PM
  • Thank you both for demistifying up my question!

    Yours sincerely,

    Evert Wiesenekker
    Friday, January 22, 2010 12:19 PM
  • When you apply LINQ query operators such as where over an EntityCollection<T> the query will be processed by LINQ to Objects. When you apply the same LINQ query operator to ObjectSet<T>, since ObjectSet<T> is an IQueryable<T>, it will use its own LINQ provider, in this case LINQ to Entities to process the query, which will result in the LINQ query to be translated to a database query.

    Hi Diego,

    how's that:

    var result1 = (from order in db.Order
                   from item in order.OrderItems
                   where item.Quantity == 123
                   select item).FirstOrDefault();
    var result2  = (from item in ord.OrderItems
                   where item.Quantity == 123
                   select item).FirstOrDefault();

    I've created a new OrderItem with Quantity set to 123, and attached it to some Order.

    In both LINQs, I retrieve from an EntityCollection, but first uses LINQ to Entities and the second uses LINQ to Objects. When ran, result1 is null but result2 points to the OrderItem.

    My question is, how EF provider can query store in the first case?

    Regards,


    Would you mind marking as answer or vote as helpful, please? It helps getting the network better.

    twitter.com/awerlang
    programmernotfound.blogspot.com
    Wednesday, March 31, 2010 12:04 PM