C#Linq连接表,其中左表可能为null

时间:2014-08-08 09:29:30

标签: c# sql sql-server database linq

请看下面的例子。在这里,为了问题,我有3个表 - mainTable tableA tableB 。在表中,PK字段表示主键,FK字段表示外来字段。

我无法加入3张桌子。在mainTable中,有一个引用tableA的字段“nullableFK”。它可能是null。因此,要连接tableA,我使用DefaultIfEmpty()使用Left Join。当我需要在tableA和tableB中匹配的字段上加入第三个表时,问题就开始了。以下示例抛出InvalidOperationException,并显示以下消息:

"The cast to value type 'System.Boolean' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type."

我尝试在没有DefaultIfEmpty的情况下加入tableB - 据我所知,它将是内连接。但是然后Sequence不包含任何元素。

目标 -

返回 mainTable tableA tableB 的值。

如果在 mainTable 中,nullableFK为null,则返回 mainTable tableA tableB 值为null,

            var query = (from mainTable in db.mainTables
                        where mainTable.PK == id

                        join tableA_ in db.tablesA on mainTable.nullableFK equals tableA_.FK into A
                        from tableA in A.DefaultIfEmpty()

                        join tableB_ in db.tablesB on tableA.PK equals tableB_.PK into B
                        from tableB in B.DefaultIfEmpty()

                        select new {
                            val1 = mainTable.fieldA,
                            val2 = tableA.fieldB,
                            val3 = tableB.fieldC
                        }).First();

回答 - 检查null中的select new {}值。

1 个答案:

答案 0 :(得分:2)

看起来OP在问题的编辑中指定了答案,但是如何实现并不是很清楚。他说要在select new {}中检查null。

我能够通过将值转换为可空类型来完成这项工作。在下面的示例中,我假设tableA.fieldB和tableB.fieldC都是int:

类型
 var query = (from mainTable in db.mainTables
              where mainTable.PK == id

              join tableA_ in db.tablesA on mainTable.nullableFK equals tableA_.FK into A
              from tableA in A.DefaultIfEmpty()

              join tableB_ in db.tablesB on tableA.PK equals tableB_.PK into B
              from tableB in B.DefaultIfEmpty()

              select new {
                  val1 = mainTable.fieldA,
                  val2 = (int?)tableA.fieldB,
                  val3 = (int?)tableB.fieldC
              }).First();