实体框架首先选择不带 .ToList() 的新 POCO
我正在创建一个带有服务层(WCF 网站)和 Silverlight 4 客户端的应用程序。 RIA 服务不是一种选择,因此我们创建中间类来来回传递。出于这个问题的目的,我们假设我正在来回传递美味 Food
对象。
public class FoodData
{
public int Id { get; set; }
public string Name { get; set; }
public Tastyness TastyLevel { get; set; }
}
EF 模型本质上是同一个类,一个包含三个基本字段的表(Tastyness 是一个 int,对应于我们的枚举 Tastyness)。
我发现自己在执行实体框架查询时经常使用这种语句:
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;
}
如果没有 .ToList() 调用,我会收到一个关于 LINQ 无法将自定义方法转换为等效查询的异常,我对此表示理解。
我的问题是关于在 .Select(...) 之前使用自定义扩展调用 .ToList() 将我们的对象转换为 Food 对象的 POCO 版本。
这里是否有更好的模式可以做,或者甚至可能是 .ToList() 的更好替代方案,它可能性能更高,因为我实际上并不需要 List<..> 的功能结果。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
使用
ToList
或AsEnumerable
的问题是您具体化整个实体并支付修复成本。如果您希望拥有仅返回所需字段的最佳 SQL,那么您应该直接进行投影,而不是使用.ToFoodData()
:转换为枚举可能会出现问题。如果是这样,请使用匿名类型:
如果检查生成的 SQL,您会发现它更简单,并且您无需支付将对象修复到 ObjectContext 中的成本。
The problem with using
ToList
orAsEnumerable
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()
:The cast to enum may be a problem. If so, go through an anonymous type:
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.
使用
AsEnumerable()
将查询转换为常规的旧 LINQ to Objects 查询,而无需创建不需要的列表编辑:请参阅 http://www.hookedonlinq.com/AsEnumerableOperator.ashx
Use
AsEnumerable()
to turn the query into a regular old LINQ to Objects query without having to create an unneeded ListEdit: See http://www.hookedonlinq.com/AsEnumerableOperator.ashx
@Craig Stuntz 的答案是正确的,但是当您有多个查询应将“Food”对象转换为“FoodData”对象时,可能会出现问题。您不希望表达式在多个位置重复 (DRY)。
解决方案可以是不使用实际返回“FoodData”对象的方法,而是使用返回用于进行转换的表达式的方法。然后您可以重新使用此方法。
要使用这个...
请记住,在使用实体框架时,您不应在应用选择表达式之前具体化 IEnumerable(使用 ToList、ToArray 等),否则实体框架将无法做出正确的选择语句,并且它将始终选择表中的所有字段。
The answer of @Craig Stuntz is correct, however there could be an issue when you have multiple queries that should transform a 'Food' object into a 'FoodData' object. You don't want the expression to be duplicated in multiple locations (DRY).
The solution can be to not have a method that actually returns a 'FoodData' object, but to have a method that returns the expression to be used to make the transformation. You can then re-use this method.
And to use this...
Remember when using Entity Framework, that you shouldn't materialize the IEnumerable (using ToList, ToArray etc.) befor applying the select expression, otherwise Entity Framework won't be able to make a correct select statement and it will always select all fields from the table.
第一个 .ToList() 不是必需的。
您是否要求结果集是 List<> ?或者仅仅 IEnumerable 或 ICollection 就足够了?如果是这样,则可能不需要最后一个 .ToList() 。
你问的是性能?您希望每个查询返回多少个实例?如果相对较少,则 .ToList() 或 .ToArray() 或其他方法不会产生任何有意义的差异。更多的是关于你需要公开什么样的功能?如果返回的对象需要可索引、可添加,并且具有 List 的其他属性,那也可以。但是,如果您所做的只是迭代返回的集合,请不要公开不需要的内容。
The first .ToList() isn't required.
Do you require that the result set be a List<>? Or would just an IEnumerable or ICollection be adequate? If so, then the last .ToList() may not be needed.
You asked about performance? How many instances do you expect to be returned per query? If it's relatively few, then .ToList() or .ToArray(), or others don't make any meaningful difference. It's more about what kind of functionality do you need to expose? If the returned object needs to be indexable, addable, and have the other properties of List, that's okay. But, if all you're doing is iterating over the returned collection, don't expose what isn't needed.