admin

如何强制LINQ to SQL对可为空的外键执行INNER JOIN?

sql

我有一个非常简单的设置。表“节点”具有可为空的外键“
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?


阅读 226

收藏
2021-07-01

共1个答案

admin

最终,我确实找到了一个很好的解决方案。答案是简单地使LINQ to SQL成为可能。像这样:

using (MyDataContext context = CreateDataContext())
{
    // Set the load options for the query (these tell LINQ that the
    // DataNode object will have an associated DataObject object just
    // as before).
    context.LoadOptions = StaticLoadOptions;

    // Run a plain old SQL query on our context.  LINQ will use the
    // results to populate the node object (including its DataObject
    // property, thanks to the load options).
    DataNode node = context.ExecuteQuery<DataNode>(
        "SELECT * FROM Node INNER JOIN Object " +
        "ON Node.ObjectId = Object.ObjectId " +
        "WHERE ObjectId = @p0",
        objectId).FirstOrDefault();

    //...
}
2021-07-01