为什么这个LINQ表达式会打破我的循环&转换逻辑? [英] Why does this LINQ expression break my loop & conversion logic?

查看:154
本文介绍了为什么这个LINQ表达式会打破我的循环&转换逻辑?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景

ArticleService 是一个提供前端图层的方法的类,它的两个基本职责是将ViewModels( ArticleViewModel )转换为相应的模型(<$当保存数据时,反过来,在获取数据时将模型转换为ViewModel ...所以经常创建一个构建ViewModel对象的私有方法:$ b $(code> Article b

  private ArticleViewModel BuildViewModel(Article a)
{
return new ArticleViewModel {Title = a.Title / * all properties * /}



$ b $ ArticleService 提供了一种方法来从数据存储中获取所有文章,并将它们返回为ViewModels: public IEnumerable< ArticleViewModel> All()



调用类像这样使用它: var articleViewModels = _articleService.All(); <

$ p
$ b $ p













我最初用 foreach 循环写了 All()> b
$ b

  private IEnumerable< ArticleViewModel> All()
{
var viewModels = new List< ArticleViewModel>();
foreach(var article in _db.Articles)
viewModels.Add(BuildViewModel(article));
返回viewModels;

$ / code>

运行良好 - articleViewModels 是所有视图模型的实例化列表。

接下来,我使用ReSharper将此循环转换为LINQ语句以获得性能和可爱,然后将赋值语句与返回声明。结果:

  private IEnumerable< ArticleViewModel> All()
{
return _db.Articles.Select(article => BuildViewModel(article))。ToList();

我调试了LINQ语句和野兽唤醒:


LINQ to Entities无法识别ArticleViewModel
BuildViewModel(Article)方法,并且此方法无法转换为存储表达式。



问题 - 为什么这个LINQ语句会破坏我的代码?



<注意:回到一个显式的声明,赋值,返回值与LINQ语句一起工作,所以我几乎可以肯定这是与lambda逻辑有关的。

解决方案


问题 - 为什么这个LINQ语句会破坏我的代码?

由于LINQ to Entities试图将 BuildViewModel 转换为SQL。它不知道如何,所以它死了悲惨。

在您的原始版本中,您是实体从数据库流到您的本地框,然后做投影使用 BuildViewModel 客户端。这很好。
$ b


所以我几乎可以肯定这是与lambda逻辑有关的。

blockquote>

不可以。这是因为LINQ to Entities不能将 BuildViewModel 转换为SQL。如果使用lambda表达式来表示投影,则无关紧要。



您可以像这样重写代码:

  return _db。文章。 
.AsEnumerable()
.Select(article => BuildViewModel(article))。ToList();

这会导致 _db.Articles 被处理作为一个普通的老enumerable,然后做投影客户端。现在LINQ to Entities不需要弄清楚如何处理 BuildViewModel


Background

ArticleService is a class that provides methods for front-end layers to facilitate business with the back-end.

Two of its base responsibilities are to convert ViewModels (ArticleViewModel) to the appropriate Models (Article) when persisting data, and the reverse, convert Models to ViewModels when fetching data... so often that I created a private method building ViewModel objects:

private ArticleViewModel BuildViewModel(Article a)
{
    return new ArticleViewModel { Title = a.Title /* all properties */ }
}

Moving along, the ArticleService provides a method to fetch all articles from the data store, returning them as ViewModels: public IEnumerable<ArticleViewModel> All()

A calling class uses it like this: var articleViewModels = _articleService.All();

Simple, right?

Problem:

I originally wrote All() lazily with a classic foreach loop:

private IEnumerable<ArticleViewModel> All()
{
    var viewModels = new List<ArticleViewModel>();
    foreach (var article in _db.Articles)
        viewModels.Add(BuildViewModel(article));
    return viewModels;
}

It worked fine - articleViewModels was an instantiate list of all view models.

Next, I used ReSharper to convert this loop to a LINQ statement for performance and prettiness, and then combined the assignment statement with the return statement. Result:

private IEnumerable<ArticleViewModel> All()
{
    return _db.Articles.Select(article => BuildViewModel(article)).ToList();
}

I debugged the LINQ statement and the beast awakened:

LINQ to Entities does not recognize the method 'ArticleViewModel BuildViewModel(Article)' and this method cannot be translated into a store expression.

Question - Why does this LINQ statement break my code?

Note: Stepping back to an explicit declaration, assignment, return worked with the LINQ statement, so I'm almost certain it's something to do with the lambda logic.

解决方案

Question - Why does this LINQ statement break my code?

Because LINQ to Entities is trying to translate BuildViewModel into SQL. It doesn't know how, so it dies miserably.

In your original version, you were streaming the entity from the database to your local box, and then doing the projection using BuildViewModel client-side. That's fine.

so I'm almost certain it's something to do with the lambda logic.

Nope. It's because LINQ to Entities can't translate BuildViewModel into SQL. It doesn't matter if you use a lambda expression to express the projection or not.

You can rewrite the code like this:

return _db.Articles.
          .AsEnumerable()
          .Select(article => BuildViewModel(article)).ToList();

This causes _db.Articles to be treated as a plain old enumerable, and then does the projection client side. Now LINQ to Entities doesn't have to figure out what to do with BuildViewModel.

这篇关于为什么这个LINQ表达式会打破我的循环&amp;转换逻辑?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆