c# - 具有多个 GroupBy 要求的多重联接的 LINQ 扩展方法

标签 c# entity-framework linq

作为学习 EF 的练习,我有以下 4 个表格。 Person 1toM订单 M2M通过 OrderProducts 获取产品(性别是一个 Enum >):

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Gender Gender { get; set; }

    public IList<Order> Orders { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public int PersonId { get; set; }
    public Person Person { get; set; }

    public IList<OrderProduct> OrderProducts { get; set; }
}

public class OrderProduct
{
    public int Id { get; set; }
    public int Qty { get; set; }
    public Order Order { get; set; }
    public int OrderId { get; set; }
    public Product Product { get; set; }
    public int ProductId { get; set; }
}

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }

    public IList<OrderProduct> OrderProducts { get; set; }
}

我正在尝试使用 LINQ 扩展方法生成以下内容:

A list of products and total [=Sum(OrderProducts.Qty * Product.Price)] spent, grouped by product name then grouped by gender.

结果看起来像这样:

Female  
    Ball      $655.60
    Bat     $1,925.40
    Glasses   $518.31
    Etc...
Male
    Ball    $1,892.30
    Bat     $3,947.07
    Glasses $1,315.71
    Etc...

我致力于LINQ扩展方法,并希望我也能在这里开发一些最佳实践。我现在不知道如何按 ProductName 分组并将 Qty * Price 按产品汇总为总计:

var prodsalesbygender = context.Orders
    .GroupBy(o => new 
    {
            Gender = o.Person.Gender
    })
    .Select(g => new
    {
        ProductName = g.Select(o => o.OrderProducts.Select(op => op.Product.Name)),
        Qty = g.Select(o => o.OrderProducts.Select(op => op.Qty)),
        Price = g.Select(o => o.OrderProducts.Select(op => op.Product.Price))
    }
);

我尝试将 .GroupBy(g => g.ProductName) 添加到末尾,但收到错误“调用“GroupBy”方法的关键选择器类型为在底层商店提供商中不具有可比性。”。

最佳答案

我想你已经快到了.. 试试这个:

       var prodsalesbygender = context.Orders
                                      .GroupBy(o => new
                                      {
                                          Gender = o.Person.Gender
                                      })
                                      .Select(g => new
                                      {
                                          Gender = g.Key,
                                          Products = g.Select(o => o.OrderProducts
                                                                    .GroupBy(op => op.Product)
                                                                    .Select(op => new
                                                                    {
                                                                        ProductName = op.Key.Name,
                                                                        Qty = op.Sum(op2 => op2.Qty),
                                                                        Price = op.Select(x => x.Product.Price)
                                                                                  .First(),
                                                                    })
                                                                    .Select(x => new
                                                                    {
                                                                        ProducName = x.ProductName,
                                                                        Qty = x.Qty,
                                                                        Price = x.Price,
                                                                        TotalPrice = x.Qty * x.Price
                                                                    }))
                                      });

简而言之,你只需要更多的投影。在我建议的解决方案中,首先按性别分组。下一步是直接投影性别和“产品列表”(是的,最难解决的部分是 OrderProducts)。在Products中,我们按产品名称对其进行分组,然后获取总数量(Qty)并设置价格 - 假设价格相同产品是恒定的。下一步是设置 TotalPrice,即 Qty * Price 内容。

诗。我充分意识到这个查询有很多缺陷。也许LINQ专家可以在这方面提供更好的帮助。

这将产生一个类似于以下内容的类:

  {
    Gender Gender
    IEnumerable<{ ProductName, Qty, Price, TotalPrice }> Products
  }

是的,匿名类型就这么多了..

尽管如此,我对否决票感到困惑,因为问题包含有问题的模型和 OP 提供的尝试。

关于c# - 具有多个 GroupBy 要求的多重联接的 LINQ 扩展方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46965897/

相关文章:

c# - 使用 DbContext 和 TenantId 的 Multi-Tenancy - 拦截器、过滤器、EF 代码优先

c# - 返回计数列表并按 id linq to sql 分组

c# - 创建既不是 true 也不是 false 的 bool 值

c# - 查看一组实数的快速方法

c# - 允许空外键 GUID

c# - EntityFramework,在配置中找不到指定的store provider,或者是无效的

c# - 我如何使用 Linq 从列表中取出两条随机记录?

C# 根据多个条件过滤列表中的项目

c# - 从字符串中获取随机的单词序列?

c# - 需要一种更好的方法来将多个值与属性进行比较并返回 true;