下面是一个例子:
假设我有三张桌子,国家,人民和城市。城市记录有一个标识国家的不可为空的外键字段。人物记录有
可空的
识别一个国家的外国关键领域——它们可能来自不再存在的东欧国家。
我想从人口和城市列表中创建一个国家的组合列表:
var people = dbContext.People.Where(...);
var cities = dbContext.Cities.Where(...);
var countries = cities.Select(c=>c.Country);
countries = countries.Union(people.Select(p=>p.Country));
问题出在最后一行。由于并非所有人员记录都有匹配的国家/地区记录,因此Linq(正确地)正在创建一个查询,以确保每个国家/地区以外的人员都有一个填充了空值的行。对于调试器,这似乎是通过创建entra虚拟列调用“[测试]”来完成的。
SELECT [t2].[test], [t2].[CountryID], [t2].[Name]
FROM [dbo].[People] AS [t0]
LEFT OUTER JOIN (
SELECT 1 AS [test], [t1].[CountryID], [t1].[Name]
FROM [dbo].[Countries] AS [t1]
) AS [t2] ON [t2].[CountryID] = [t0].[CountryID]
当代码端的额外列[test]被静默地删除(结果被标识为iqueryable)时,在SQL端,它最明显地在那里,当我将它与一个正常的国家选择语句结合时,会导致查询被拒绝。
在最后一种情况下,我不需要或不需要额外的虚拟行-在我已经包含的完整程序中
people.Where(p=>p.CountryID != null).Select(p=>p.Country)
以及尝试
p=>Country != null
.
但是,Linq不认识到这将阻止空行,因此仍然插入测试列。由于测试列是不可见的,所以我没有明显的方法可以将它从另外报告为IQueryable对象的对象中“删除”。最终的结果是关于我的union构造具有不相等的列数的运行时错误。
如何在可为空的关系上强制内部联接,或者通过排除不可见的测试列使联合按我的意愿工作?