one*_*mer 3 c# linq foreach lambda linq-to-entities
ArticleService 是一个为前端层提供方法以促进后端业务的类.
它的两个基本职责是在持久化数据时将ViewModels(ArticleViewModel)转换为适当的Models(Article),反过来,在获取数据时将模型转换为ViewModel ...所以我经常创建一个构建ViewModel对象的私有方法:
private ArticleViewModel BuildViewModel(Article a)
{
return new ArticleViewModel { Title = a.Title /* all properties */ }
}
Run Code Online (Sandbox Code Playgroud)
继续,ArticleService提供了一种从数据存储中获取所有文章的方法,将它们作为ViewModels返回:public IEnumerable<ArticleViewModel> All()
调用类使用它如下: var articleViewModels = _articleService.All();
简单吧?
我最初All()懒得写经典foreach循环:
private IEnumerable<ArticleViewModel> All()
{
var viewModels = new List<ArticleViewModel>();
foreach (var article in _db.Articles)
viewModels.Add(BuildViewModel(article));
return viewModels;
}
Run Code Online (Sandbox Code Playgroud)
它工作得很好 - articleViewModels是所有视图模型的实例化列表.
接下来,我使用ReSharper将此循环转换为LINQ语句以获得性能和漂亮,然后将赋值语句与return语句结合使用.结果:
private IEnumerable<ArticleViewModel> All()
{
return _db.Articles.Select(article => BuildViewModel(article)).ToList();
}
Run Code Online (Sandbox Code Playgroud)
我调试了LINQ语句并唤醒了野兽:
LINQ to Entities无法识别方法'ArticleViewModel BuildViewModel(Article)'并且此方法无法转换为商店表达式.
注意:退回到显式声明,赋值,返回使用LINQ语句,所以我几乎可以肯定它与lambda逻辑有关.
问题 - 为什么这个LINQ语句会破坏我的代码?
因为LINQ to Entities正试图转换BuildViewModel为SQL.它不知道如何,所以它悲惨地死去.
在原始版本中,您将实体从数据库流式传输到本地框,然后使用BuildViewModel客户端进行投影.没关系.
所以我几乎可以肯定它与lambda逻辑有关.
不.这是因为LINQ to Entities无法转换BuildViewModel为SQL.如果使用lambda表达式来表达投影,则无关紧要.
您可以像这样重写代码:
return _db.Articles.
.AsEnumerable()
.Select(article => BuildViewModel(article)).ToList();
Run Code Online (Sandbox Code Playgroud)
这导致_db.Articles被视为普通的旧的可枚举,然后是投影客户端.现在LINQ to Entities不必弄清楚如何处理BuildViewModel.
| 归档时间: |
|
| 查看次数: |
523 次 |
| 最近记录: |