我有一个非常简单的设置。表“Node”有一个可为空的外键“ObjectId”。这在我的数据库模型中表示为一对多关联。现在,我想运行一个查询,为我提供具有特定对象 ID 的所有节点对象。在直接 SQL 中,这非常简单:
SELECT Node.*, Object.*
FROM Node INNER JOIN Object
ON Node.ObjectId = Object.ObjectId
WHERE Node.ObjectId = @objectId
但现在我想在 LINQ to SQL 中做同样的事情:
private static Func<MyDataContext, string, IQueryable<DataNode>> _queryGet =
CompiledQuery.Compile(
(MyDataContext context, string objectId) =>
(from node in context.DataNodes
where node.ObjectId == objectId
select node));
var loadOptions = new DataLoadOptions();
loadOptions.LoadWith<DataNode>(node => node.DataObject);
context.LoadOptions = loadOptions;
DataNode node = _queryGet.Invoke(context, objectId).FirstOrDefault();
...
令人沮丧的是,LINQ 总是为此查询生成一个 LEFT OUTER JOIN,而我尝试过的任何事情都没有什么不同。
从表面上看,这似乎是有道理的。 ObjectId 外键可以为空,因此某些节点不会有关联的对象。但在我的查询中,我提供了一个对象 ID。我对没有关联对象的节点不感兴趣。
在这种情况下,INNER JOIN 是正确的做法,但我如何说服 LINQ?
最佳答案
我想你只需要让它成为一个左外连接。我想象当表达式树被转换为 SQL 时,连接和相等谓词被认为是结果查询的独立部分。换句话说,LEFT OUTER JOIN 之所以存在,是因为您要加入一个可为空的外键,并且等式部分写在后面(可以这么说)。
没有按照您的意愿进行翻译真的很重要吗?当您使用 LINQ to SQL 时,您并不总是获得可能的最高效查询这一事实是一种可接受的权衡。大多数时候,如果您没有做任何疯狂的事情,查询会非常有效,并且如果您真的认为它会影响性能或其他什么,您总是可以编写 LINQ to SQL 可以使用的存储过程.
关于c# - 如何强制 LINQ to SQL 对可为空的外键执行 INNER JOIN?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3981813/