Framework for Entities Choose a new POCO without. ToList() comes first.

entity-framework linq linq-to-entities linq-to-sql

Question

I'm creating an application with a service layer (WCF Website) and a Silverlight 4 Client. RIA Services are not an option, so we create intermediary classes to pass back and forth. For the purpose of this question let's assume I'm passing back and forth Tasty Food Objects.

public class FoodData
{
  public int Id { get; set; }
  public string Name { get; set; }
  public Tastyness TastyLevel { get; set; }
}

The EF Model is essentially the same class, a table with three basic fields (the Tastyness is an int that corresponds to our enum Tastyness).

I find myself using this kind of statement a lot when doing Entity Framework queries:

public List<FoodData> GetDeliciousFoods()
{
  var deliciousFoods = entities.Foods
                               .Where(f => f.Tastyness == (int)Tastyness.Delicious)
                               .ToList()  // Necessary? And if so, best performance with List, Array, other?
                               .Select(dFood => dFood.ToFoodData())
                               .ToList();

  return deliciousFoods;
}

Without the .ToList() call I get an exception about LINQ not being able to translate the custom method to a query equivalent, which I understand.

My question is about the call to .ToList() before the .Select(...) with the custom extension to convert our object to the POCO version of the Food object.

Is there a better pattern to do here, or maybe even a better alternative to .ToList() that may be more performant since I don't really require the functionality of the List<..> result.

1
15
3/3/2011 8:37:33 PM

Accepted Answer

The problem with using ToList or AsEnumerable is that you materialize the entire entity and pay the cost of fixup. If you want to have the best possible SQL which returns only the needed fields, then you should project directly rather than using .ToFoodData():

var deliciousFoods = entities.Foods
                             .Where(f => f.Tastyness == (int)Tastyness.Delicious)
                             .Select(dFood => new FoodData
                                  {
                                      Id = dFood.Id,
                                      Name = dFood.Name,
                                      TastyLevel = (Tastyness)dFood.Tastyness
                                  });

The cast to enum may be a problem. If so, go through an anonymous type:

var deliciousFoods = entities.Foods
                             .Where(f => f.Tastyness == (int)Tastyness.Delicious)
                             .Select(dFood => new FoodData
                                  {
                                      Id = dFood.Id,
                                      Name = dFood.Name,
                                      TastyLevel = dFood.Tastyness
                                  })
                             .AsEnumerable()
                             .Select(dFood => new FoodData
                                  {
                                      Id = dFood.Id,
                                      Name = dFood.Name,
                                      TastyLevel = (Tastyness)dFood.TastyLevel
                                  });

If you examine the resulting SQL, you'll see it's simpler, and you don't pay the cost of fixing up objects into the ObjectContext.

12
3/3/2011 10:45:48 PM

Popular Answer

Use AsEnumerable() to turn the query into a regular old LINQ to Objects query without having to create an unneeded List

var deliciousFoods = entities.Foods
                               .Where(f => f.Tastyness == (int)Tastyness.Delicious)
                               .AsEnumerable()
                               .Select(dFood => dFood.ToFoodData())
                               .ToList();

Edit: See http://www.hookedonlinq.com/AsEnumerableOperator.ashx



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow