我有一个非常简单的设置。表“节点”具有可为空的外键“ 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?
最终,我确实找到了一个很好的解决方案。答案是简单地使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(); //... }