【问题标题】:Linq average query and projectionLinq 平均查询和投影
【发布时间】:2014-04-25 10:02:57
【问题描述】:

我正在尝试从评分表中获取人们的平均评分,我有以下代码。我将结果投影到 PersonVm 类中

    public IEnumerable SrchArtisansByBSSLR(string q, int s = 0, int l = 0, double z = 0)
    {
        var list = from item in _entities.People
                   where item.Skill.SkillName == q && item.StateId == s && item.LGAId == l && item.Ratings.Any(g => g.RatingValue == z)
                   group item by item.PersonId into d
                   select new PersonVm
                   {
                       PersonId = d.Key,
                       Rating = d.Average(x=>x.Ratings.Any(y=>y.RatingValue)),  
                       LastName = item.LastName,
                       Skill = item.Skill.SkillName,
                       StateId = item.StateId,
                       LGAId = item.LGAId,
                       Address = item.Address,
                       Email = item.Email,
                       ImageSource = @"\Photos\" + item.ImageSource,
                       RegDate = item.RegDate                       
                   };
        return list;                   
    }

我收到以下错误

无法将 lambda 表达式转换为委托类型“System.Func”,因为块中的某些返回类型不能隐式转换为委托返回类型

和

不能隐式转换类型'double'?到“布尔”ArtsHub.DataLayer

请问我的平均代码有什么问题?

【问题讨论】:

  • 你可以试试Rating = d.Ratings.Average()
  • .Any() 返回一个布尔值 - 你的意思是 .First()?
  • @Yahya 我试过 Rating = d.Ratings.Average() 它无法将其视为可访问的成员
  • @RGraham 我带来了这些错误 1.无法将 lambda 表达式转换为委托类型 'System.Func' 因为块中的某些返回类型不可隐式转换到委托返回类型 2。不能隐式转换类型“双”?到“布尔”

标签: c# linq entity-framework linq-to-entities


【解决方案1】:

注意.ToList()之前... .GroupBy(item => new ...是导致你的数据先在内存中获取,group by会在内存中完成,你可以比较这两个查询的执行时间。

var list = _entities.People
            .Where(item => item.Skill.SkillName == q && 
                           item.StateId == s && 
                           item.LGAId == l && 
                           item.Ratings.Any(g => g.RatingValue == z))
            .ToList()
            .GroupBy(item => new 
            {
                item.PersonId,
                item.LastName,
                item.Skill.SkillName,
                item.StateId,
                item.LGAId,
                item.Address,
                item.Email,
                item.ImageSource,
                item.RegDate
            })
            .Select(d => new PersonVm() 
            {
                PersonId = d.Key,
                Rating = d.Average(x => x.Ratings.Any(y => y.RatingValue)),
                LastName = d.Key.LastName,
                Skill = d.Key.SkillName,
                StateId = d.Key.StateId,
                LGAId = d.Key.LGAId,
                Address = d.Key.Address,
                Email = d.Key.Email,
                ImageSource = @"\Photos\" + d.Key.ImageSource,
                RegDate = d.Key.RegDate
            })
            .ToList();

【讨论】:

  • 你好 Amir,在尝试这个时,我在 Rating 属性 (Rating=d.Average(x=>x.Ratings.Any( y=>y.RatingValue))) 然后我把它改成这个(Rating = d.Average(x => x.Ratings.Sum(y => y.RatingValue)),)。这有效,但不是返回平均值,而是返回总和。请问你有什么建议,我试图解决它无济于事......谢谢
【解决方案2】:

这个x=>x.Ratings.Any(y=>y.RatingValue)返回一个bool作为结果,因为.Any()产生boolean结果类型,你需要得到一个lambda到.Average(),它产生一个type与@的类型相同987654328@财产。

似乎Rating 是double?,所以你需要将lambda 传递给.Average(),它返回double? 或double 或者可以转换为double? 的东西

我认为你需要这个:

Rating = d.Average(x => x.Ratings.Sum(y => y.RatingValue))

【讨论】:

  • 这对眼睛和编译器来说看起来如此清晰和合乎逻辑。它只是在我用我想访问的其他一些属性更新问题后无法访问它们才起作用。是不是分组后我无法再次访问“项目”?你会推荐什么?谢谢...
  • 您的问题不清楚。而不是我,其他人(在 cmets 中)没想到您的意思是如何访问已分组的项目...最后关于您的问题,您是否包含所有这些属性,对于每个 PersonId 都相同?
  • 我的意思是你的回答很清楚,它修复了错误。谢谢。我的意思是,在我带来这些属性后,我无法使用它们。对于这个问题,是的,它们对于每个 personId 都是相同的,只是我将投影到 PersonVm 中,因此不会选择所有列...再次感谢...
  • aha,这是一个误会,因为每个人的id都是一样的,你需要添加它们到group by,我需要添加另一个帖子,检查一下
【解决方案3】:

您需要将它们添加到group by。

var list = from item in _entities.People

            where item.Skill.SkillName == q && item.StateId == s && item.LGAId == l && item.Ratings.Any(g => g.RatingValue == z)

            group item by new { 
                item.PersonId,
                item.LastName,
                item.Skill.SkillName,
                item.StateId,
                item.LGAId,
                item.Address,
                item.Email,
                item.ImageSource,
                item.RegDate
            } into d

            select new PersonVm
            {
                 PersonId = d.Key,
                 Rating = d.Average(x => x.Ratings.Any(y => y.RatingValue)),
                 LastName = d.Key.LastName,
                 Skill = d.Key.SkillName,
                 StateId = d.Key.StateId,
                 LGAId = d.Key.LGAId,
                 Address = d.Key.Address,
                 Email = d.Key.Email,
                 ImageSource = @"\Photos\" + d.Key.ImageSource,
                 RegDate = d.Key.RegDate
            };
return list; 

【讨论】:

  • 非常感谢您完美运行。我只是想知道如果我使用它来搜索数十万行,这会对性能产生什么影响......
  • group by 特别是当您按复杂对象分组项目时速度很慢,在这种情况下,先获取数据然后在内存中分组更有效,通过这种方式可以提高性能,并执行您的查询,我需要添加另一篇文章来编写一个查询,该查询首先获取数据然后进行分组
猜你喜欢
  • 1970-01-01
  • 2012-04-01
  • 2015-05-29
  • 2015-10-15
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
  • 2012-12-28
  • 1970-01-01
相关资源
最近更新 更多