如果为空+匿名类型+分组,则LINQ左连接+默认值

时间:2014-05-15 16:40:49

标签: c# linq grouping nullreferenceexception anonymous-class

我想知道给定问题的最佳解决方案是什么,简化为:

  1. 我有两个本地存储的sql表,我想加入(左连接)和Default If Empty属性,然后我需要对这些数据进行分组

  2. 在访问obj.column之前,我不想检查(obj == null),如果给定行的连接不成功,则会抛出错误

  3. 数据

    LeftTable    RightTable    OUTPUT
     A B C        A B Z         A  B  C  Z
     1 1 1        1 1 5         1  1  1  5
     1 2 2        1 2 6         1  2  2  6
     5 6 7                      5  6  7 null
    

    代码

    var RightTable = from row in Source
                     where row.X > 10
                     select new {        // anonymous type that I want to keep
                        A = row.AAA,
                        B = row.BBB,
                        Z = row.ZZZ
                     };
    
    var test = from left in LeftTable
               from right in RightTable
                 .Where(right => right.A == left.A
                    && right.B == left.B )
                 .DefaultIfEmpty( /* XXXXX */ )   //<-- this line is interesting
               group left by new {
                 left.A
                 left.B
                 left.C
                 right.Z  //<-- this will throw null exception error
               } into g     //  but I don't want to change it to 
               select g;    //  Z = (right != null) ? right.Z : (string) null
    

    问题:

    我可以在DefaultIfEmpty中填充一个我能从这段代码中动态获取的参数吗?

    我知道我可以创建一个类似下面的帮助器类型并替换RightTable中的匿名类型选择并在默认情况下使用它,如果为空:

    DefaultIfEmpty(new Helper())
    

    但我不想这样做,因为我必须在现实生活场景中处理20,30多个专栏。

    public class Helper {
        public string A,
        public string B,
        public string C
    }
    

    非常感谢你的时间,如果你读到这里。希望在这里得到一些解决方案。 感谢。

2 个答案:

答案 0 :(得分:1)

我认为code说明了一切:

var LeftTable = new[]
        {
            new { A = 1, B=1, C=1 },
            new { A = 1, B=2, C=2 },
            new { A = 5, B=6, C=7 }
        }
        .ToList();


        var RightTable = new[]
        {
            new { A = 1, B=1, Z=5 },
            new { A = 1, B=2, Z=6 }
        }
        .ToList();


        var query = (from left in LeftTable
                     join right in RightTable
                        on new { left.A, left.B } equals new { right.A, right.B }
                        into JoinedList
                     from right in JoinedList.DefaultIfEmpty(new { A = 0, B = 0, Z = 0 })
                     group left by new
                     {
                         left.A,
                         left.B,
                         left.C,
                         right.Z
                     } into g
                     select g)
                    .ToList();

答案 1 :(得分:0)

我和你有同样的问题,我必须找到办法,想出这样的事情(很简单的例子):

var toReturn = from left in bd.leftys
               join rights in myAnonimousGroupedList on left.Id equals rights.leftId into joinings
               from right in joinings.DefaultIfEmpty()
               select new {
                   left.A
                   left.B
                   left.C
                   // Z = right != null ? right.Z : 0
                   Z = joinings.Any() ? right.Z : 0 // see what i did here?
               };