使用AutoMapper进行LINQ GroupBy聚合

时间:2017-10-20 23:55:07

标签: c# linq automapper

试图让查询起作用,但老实说不确定如何(或者甚至是否可能)继续查询,因为我尝试过的所有内容都没有用。

总共查询6个表:Person,PersonVote,PersonCategory,Category,City和FirstAdminDivision。

PersonVote是一个用户评论表,包含一个名为Vote的列,它是一个小数,接受1-5的值(5为"最好")。 FirstAdminDivision将成为美国各州的代名词,如加利福尼亚州。 Person表有一个名为CityId的列,它是City的外键。我认为其他表格大多是不言自明的,所以除非需要,否则我不会发表评论。

我的目标是创建一个查询,返回最受欢迎的"这些人将基于PersonVote表上特定人员的所有投票的平均值。例如,如果一个人有3票,所有3票都是" 5"然后他们会在列表中排在第一位......此时并不真正关心二级排序......例如......就像大多数选票中的选票会赢得#34;。

我在没有AutoMapper的情况下工作,但我喜欢AM能够使用ProjectTo扩展方法进行投影,因为代码非常干净和可读,并且如果可能的话,我更愿意使用这种方法但是没有有幸运气。

这就是我所做的工作....所以基本上,我试图看看是否可以使用ProjectTo而不是LINQ的Select方法。

List<PersonModel> people = db.People
                    .GroupBy(x => x.PersonId)
                    .Select(x => new PersonModel
                    {
                        PersonId = x.FirstOrDefault().PersonId,
                        Name = x.FirstOrDefault().Name,
                        LocationDisplay = x.FirstOrDefault().City.Name + ", " + x.FirstOrDefault().City.FirstAdminDivision.Name,
                        AverageVote = x.FirstOrDefault().PersonVotes.Average(y => y.Vote),
                        Categories = x.FirstOrDefault().PersonCategories.Select(y => new CategoryModel
                        {
                            CategoryId = y.CategoryId,
                            Name = y.Category.Name
                        }).ToList()
                    })
                    .OrderByDescending(x => x.AverageVote)
                    .ToList();

1 个答案:

答案 0 :(得分:3)

通过查看您的代码示例,我尝试确定您的模型将是什么以设置示例。我只使用一些属性来实现显示功能:

public class People
{
    public int PeronId { get; set; }
    public string Name { get; set; }
    public City City { get; set; }
    public IList<PersonVotes> PersonVoes { get; set; }
}

public class PersonVotes
{
    public int Vote { get; set; }
}

public class City
{
    public string Name { get; set; }
}

public class FirstAdminDivision
{
    public string Name { get; set; }
}

public class PersonModel
{
    public int PersonId { get; set; }
    public string Name { get; set; }
    public string LocationDisplay { get; set; }
    public double AverageVote { get; set; }
}

要使用ProjectTo扩展我,然后通过静态API初始化AM:

        Mapper.Initialize(cfg =>
        {
            cfg.CreateMap<IEnumerable<People>, PersonModel>()
                .ForMember(
                    model => model.LocationDisplay, 
                    conf => conf.MapFrom(p => p.FirstOrDefault().City.Name))
                .ForMember(
                    model => model.AverageVote,
                    conf => conf.MapFrom(p => p.FirstOrDefault().PersonVoes.Average(votes => votes.Vote)));
        });

因此给出了以下对象:

var people = new List<People>()
        {
            new People
            {
                PeronId = 1,
                City = new City
                {
                    Name = "XXXX"
                },
                PersonVoes = new List<PersonVotes>
                {
                    new PersonVotes
                    {
                        Vote = 4
                    },
                    new PersonVotes
                    {
                        Vote = 3
                    }
                }

            }
        };

然后我会查询:

var result = people
            .GroupBy(p => p.PeronId)
            .Select(peoples => peoples)
            .AsQueryable()
            .ProjectTo<PersonModel>();

我只是在内存对象中使用,这就是为什么我转换为IQueryable以在AM中使用ProjectTo扩展方法。

我希望这是你正在寻找的东西。欢呼声,

更新LINQ TO ENTITIES QUERY:

var result = db.People
    .GroupBy(p => p.PersonId)
    .ProjectTo<PersonModel>(base.ConfigProvider)  // AM requires me to pass Mapping Provider here.
    .OrderByDescending(x => x.AverageVote)
    .ToList();