【问题标题】:A lambda expression with a statement body cannot be converted to an expression tree(Lambda and Linq)带有语句体的 lambda 表达式不能转换为表达式树(Lambda 和 Linq)
【发布时间】:2016-09-17 07:37:35
【问题描述】:

搜索了很多,但没有找到适合我的解决方案。我在lambda expression 中引入了一个变量,这就是显示此错误消息的原因。此外,我可以解决编写“SQL Like Linq Query”的问题,但这不是我的期望..我的期望是在“Linq Using Lambda Expression”中引入变量。有没有可能??

带有语句体的 lambda 表达式不能转换为表达式树。

这是我的代码:

IQueryable<IGrouping<int, AnimalFood>> animalFoods = db.AnimalFoods.GroupBy(x => x.FoodId);
IQueryable<FoodSummaryViewModel> foodSummaryViewModel = animalFoods.Select(g =>
{
    var animalFood = g.FirstOrDefault();
    return new FoodSummaryViewModel()
    {
        FoodName = animalFood.Food.FoodName,
        FoodPrice = animalFood.Food.UnitPrice,
        TotalFoodQuantity = g.Sum(x => x.Animal.AnimalQuantity * x.FoodQuantity),
        TotalPrice = g.Sum(x => x.Animal.AnimalQuantity * x.FoodQuantity) * animalFood.Food.UnitPrice
    };
});
return foodSummaryViewModel.ToList();

【问题讨论】:

标签: c# .net linq lambda


【解决方案1】:

错误信息非常清楚:您有一个带有语句体的 lambda 表达式,并且根本无法将其转换为表达式树(至少编译器不会自动转换)。因此,您的 linq 提供程序无法从中创建查询以发送到数据库(即使您手动创建了表达式树,这并非易事,您的 linq 提供程序也无法将其转换为 SQL 查询)。

你有两个选择。选项一是重写您的查询,使其不包含语句正文,正如其他人所展示的那样。

另一个选项是在内存中执行部分查询,使用 linq to objects。您必须小心使用这种方法,并避免从数据库中获取过多数据。但这样做的方法是:

IEnumerable<IGrouping<int, AnimalFood>> animalFoods = 
    db.AnimalFoods.GroupBy(x => x.FoodId).AsEnumerable();
IEnumerable<FoodSummaryViewModel> foodSummaryViewModel = animalFoods.Select(g =>
{
    var animalFood = g.FirstOrDefault();
    return new FoodSummaryViewModel()
    {
        FoodName = animalFood.Food.FoodName,
        FoodPrice = animalFood.Food.UnitPrice,
        TotalFoodQuantity = g.Sum(x => x.Animal.AnimalQuantity * x.FoodQuantity),
        TotalPrice = g.Sum(x => x.Animal.AnimalQuantity * x.FoodQuantity) * animalFood.Food.UnitPrice
    };
});
return foodSummaryViewModel.ToList();

这可能会给你你认为你想要的东西,但这可能不是一个好主意。您的选择器正在使用 AnimalFood.Animal.AnimalQuatity 属性链,这可能会导致延迟加载,具体取决于您的 Linq 提供程序。而且,如果您已将其配置为使用预先加载,则可能不会更好,因为您可能加载了太多数据。

所以你可能会更好地重写你的查询。你确定这样的事情不起作用吗:

var q = from food in db.Foods
        select new FoodSummaryViewModel
        {
            FoodName = food.FoodName,
            FoodPrice = food.UnitPrice,
            TotalFoodQuantity = (from fa in food.AnimalFoods 
                                 select fa.Animal.AnimalQuantity).Sum() * food.FoodQuantity
            TotalPrice = (from fa in food.AnimalFoods 
                          select fa.Animal.AnimalQuantity).Sum() * food.FoodQuantity * food.UnitPrice
        };
return q.ToList();

【讨论】:

  • 非常感谢您的解释!!
【解决方案2】:

您不能在 linq-2-db 查询中编写多行方法,因为这种多行方法无法转换为表达式树,而无法由提供程序解释并因此转换为纯 SQL 语句.你可以这样做:

var results = (from f in animalFoods
              group f by f.FoodId into groups
              let animalFood = groups.First()
              select new FoodSummaryViewModel()
              {
                 FoodName = animalFood.Food.FoodName,
                 FoodPrice = animalFood.Food.UnitPrice,
                 TotalFoodQuantity = groups.Sum(x => x.Animal.AnimalQuantity * x.FoodQuantity),
                 TotalPrice = groups.Sum(x => x.Animal.AnimalQuantity * x.FoodQuantity) * animalFood.Food.UnitPrice
              }).ToList();

【讨论】:

  • OP 得到的错误与数据库查询翻译无关。这是一个编译时错误。
  • 谢谢!!..我知道这个解决方案..这不是我的期望..我想在“Linq using Lamda expression”而不是“SQL Like Linq query”中引入变量
  • @IvanStoev 错误是 无法将带有语句体的 lambda 表达式转换为表达式树。你认为为什么会产生这个编译错误?
  • @TanvirArjel 您可以将答案转换为 Method-Syntax 但它不可读且很难维护?你这样做有什么好处?最后,编译器将为您将上述语法转换为方法语法!所以写什么更具可读性!这就是为什么首先发明了查询语法(上面写在我的答案中)的原因!
  • 因为目前的编译器缺乏支持。您可以使用Expression 类手动创建这样的表达式树,所以它肯定可以转换,只是编译器目前不能:) 我理解你的意思,如果它被支持,那么它很可能会被转换为一些运行时错误.请注意,它可以完美地与 LINQ to Objects 可查询提供程序一起使用。
猜你喜欢
  • 2011-07-07
  • 1970-01-01
  • 1970-01-01
  • 2013-08-08
  • 2012-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多