c# Linq 交叉连接同一 table 上的行

c# Linq cross join rows on same table

我正在尝试在单个 table 上交叉连接具有不同类别 (CarreraId) 的行,并计算给定组合的点总和。 但是,使用此代码,如果没有给定类别的行(假设 CarreraId=6),则查询 return 0 项。 我希望查询 return 72 种组合(在本例中)和 0 用于不存在类别 (CarreraId) 的值。

不知道如何处理这种情况。另外,我想知道是否有办法使用 Dynamic Linq 来解决此类问题。

感谢任何帮助。

var marcas = new List<Marca>
{
    new Marca(1, 1, 0),
    new Marca(1, 5, 1), 
    
    new Marca(2, 3, 0), 
    new Marca(2, 8, 5), 
    new Marca(2, 10, 0),    
    
    new Marca(3, 1, 0), 
    
    new Marca(4, 6, 5), 
    new Marca(4, 9, 2), 
    new Marca(4, 12, 1),
    
    new Marca(5, 7, 1), 
    new Marca(5, 11, 1),    
    
     new Marca(6, 1, 0),    // <-- Comment this line to reproduce the problem
     new Marca(6, 2, 0)     // <-- Comment this line to reproduce the problem

};


var resultado = from marca1 in marcas where marca1.CarreraId == 1 orderby marca1.ParticipanteId ascending 
                from marca2 in marcas where marca2.CarreraId == 2 orderby marca1.ParticipanteId ascending
                from marca3 in marcas where marca3.CarreraId == 3 orderby marca1.ParticipanteId ascending
                from marca4 in marcas where marca4.CarreraId == 4 orderby marca1.ParticipanteId ascending
                from marca5 in marcas where marca5.CarreraId == 5 orderby marca1.ParticipanteId ascending
                from marca6 in marcas where marca6.CarreraId == 6 orderby marca6.ParticipanteId ascending 
                select new {
                            Carrera1 = marca1.ParticipanteId,
                            Carrera2 = marca2.ParticipanteId,
                            Carrera3 = marca3.ParticipanteId,
                            Carrera4 = marca4.ParticipanteId,
                            Carrera5 = marca5.ParticipanteId,
                            Carrera6 = marca6.ParticipanteId,  // Tried to use this to no avail --> Carrera6 = (marca6?.Participante == null ? 0 : marca6.Participante),
                            Puntos = marca1.Puntos + marca2.Puntos + marca3.Puntos + marca4.Puntos + marca5.Puntos + marca6.Puntos // Tried this as well --> + marca6?.Puntos
                            };
resultado.ToList().ForEach(r => Console.WriteLine(r));


record Marca(int? CarreraId, int? ParticipanteId, int? Puntos);

类似于下面的内容 - 您可能只需要 CarreraId == 6 上的 .defaultifempty

  var resultado2 = from marca1 in marcas.Where(x => x.CarreraId == 1).DefaultIfEmpty()
                   orderby marca1.ParticipanteId ascending
                   from marca2 in marcas.Where(x => x.CarreraId == 2).DefaultIfEmpty()
                   orderby marca1.ParticipanteId ascending
                   from marca3 in marcas.Where(x => x.CarreraId == 3).DefaultIfEmpty()

                   orderby marca1.ParticipanteId ascending
                   from marca4 in marcas.Where(x => x.CarreraId == 4).DefaultIfEmpty()

                   orderby marca1.ParticipanteId ascending
                   from marca5 in marcas.Where(x => x.CarreraId == 5).DefaultIfEmpty()

                   orderby marca1.ParticipanteId ascending
                   from marca6 in marcas.Where(x => x.CarreraId == 6).DefaultIfEmpty()

                   orderby marca6 == null ? 0 : marca6.ParticipanteId ascending
                   select new
                   {
                     Carrera1 = marca1.ParticipanteId,
                     Carrera2 = marca2.ParticipanteId,
                     Carrera3 = marca3.ParticipanteId,
                     Carrera4 = marca4.ParticipanteId,
                     Carrera5 = marca5.ParticipanteId,
                     Carrera6 = (marca6 == null ? 0 : marca6.ParticipanteId),
                     Puntos = marca1.Puntos + marca2.Puntos + marca3.Puntos + marca4.Puntos + marca5.Puntos + (marca6 == null ? 0 : marca6.Puntos) // 
                   };
  resultado2.ToList().ForEach(r => Console.WriteLine(r));

使用 Lambda 风格的聚合函数解决

var marcas = new List<Marca>
{
    new Marca(1, 1, 0),
    new Marca(1, 5, 1),

    new Marca(2, 3, 0),
    new Marca(2, 8, 5),
    new Marca(2, 10, 0),

    new Marca(3, 1, 0),

    new Marca(4, 6, 5),
    new Marca(4, 9, 2),
    new Marca(4, 12, 1),

    new Marca(5, 7, 1),
    new Marca(5, 11, 1),

    new Marca(6, 1, 0),
    new Marca(6, 2, 0)

};


var resultado = marcas.GroupBy(m => m.CarreraId);

var resultado1 = resultado.Skip(1)
                           .Aggregate(resultado.First()
                                        .Select(i => new List<Marca>() { i }),
                                        (previous, next) => previous
                                                            .SelectMany(m => next.Select(e => new List<Marca>(m) { e })));


record Marca(int? CarreraId, int? ParticipanteId, int? Puntos);