实体框架首先选择没有.ToList()的新POCO

Jac*_*cob 15 linq linq-to-entities entity-framework linq-to-sql

我正在创建一个带有服务层(WCF网站)和Silverlight 4客户端的应用程序.RIA服务不是一种选择,因此我们创建了来回传递的中间类.出于这个问题的目的,让我们假设我来回传递美味Food物体.

public class FoodData
{
  public int Id { get; set; }
  public string Name { get; set; }
  public Tastyness TastyLevel { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

EF模型本质上是同一个类,一个包含三个基本字段的表(Tastyness是一个与我们的enum Tastyness相对应的int).

在进行实体框架查询时,我发现自己经常使用这种语句:

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;
}
Run Code Online (Sandbox Code Playgroud)

没有.ToList()调用,我得到一个关于LINQ无法将自定义方法转换为查询等价物的异常,我理解.

我的问题是在.Select(... )之前调用.ToList(),使用自定义扩展将我们的对象转换为Food对象的POCO版本.

有没有更好的模式在这里做,或者甚至可能是更好的替代.ToList()可能更高效,因为我并不真正需要List <..>结果的功能.

Cra*_*ntz 12

使用ToList或问题AsEnumerable是您实现整个实体并支付修复费用.如果你想拥有最好的SQL,它只返回所需的字段,那么你应该直接投影而不是使用.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
                                  });
Run Code Online (Sandbox Code Playgroud)

演员到枚举可能是一个问题.如果是这样,请浏览匿名类型:

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
                                  });
Run Code Online (Sandbox Code Playgroud)

如果检查生成的SQL,您会发现它更简单,并且您不需要支付将对象修复到ObjectContext的成本.


cor*_*erm 6

使用AsEnumerable()打开查询到一个普通的旧LINQ到对象的查询,而无需创建一个不需要名单

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

编辑:请参阅http://www.hookedonlinq.com/AsEnumerableOperator.ashx