5

我正在使用 Julie Lerman 的 DbContext 书中的 BAGA 代码。我想在 LINQ 中重新创建以下 SQL 查询并将结果放入 List 集合中并且遇到问题。 http://learnentityframework.com/downloads/

SELECT * FROM baga.Locations d
LEFT JOIN Lodgings l ON d.LocationID = l.destination_id
WHERE d.Country = 'usa'
AND (l.MilesFromNearestAirport > 5 or l.MilesFromNearestAirport is null)

因此,用英语,获取位于美国的所有位置(目的地),并包括 MilesFromNearestAirport > 5 的所有相关住宿

语法无法编译,但我希望类似于下面的内容

var dests = context.Destinations
  .Where(d => d.Country == "USA" && d.Lodgings.Where(l => l.MilesFromNearestAirport > 5))
  .Select(d => d)
  .ToList();

有任何想法吗?

4

3 回答 3

7

正如@Sampath 所说,这通常是通过导航属性完成的,但我相信他的代码并不完全符合您的要求。这(我认为)更接近:

var dests = context.Destinations
           .Where(d => d.Country == "USA")
           .Select(d => 
               new { d,
                     RemoteLodgings = d.Lodgings
                         .Where(l => l.MilesFromNearestAirport > 5)}
           .ToList();

但是,如果我信守您的要求,它仍然不能满足您的要求。您想要包含住宿的位置,即部分加载的导航属性。当实体要被序列化并在一个包中发送到(Web)客户端时,这会很方便。(虽然上面的方法也可以)。

但是可以使用部分加载的导航属性创建一个集合。

这本书在第 40 页展示了如何部分加载单个实体的导航属性(简而言之:context.Entry(entity).Collection(e => e.Children).Query().Where(condition)。但如上所述,这只是一个实例。对于实体集合,这不是最好的方法。

有趣的是(正如我的一位同事发现的那样),您可以通过将所需的集合元素分别加载到上下文中来轻松地为实体集合执行此操作:

var lodgings = context.Lodgings
              .Where(l => l.MilesFromNearestAirport > 5 
                       && l.Destination.Country == "USA")
              .ToList();

现在,如果您循环浏览,context.Destinations.Where(d => d.Country == "USA")您会看到他们的住所都装满了“ >5”。可能是因为此时 EF 执行了关系修复。(延迟加载禁用,因为延迟加载将完全加载导航属性)。

编辑(在您发表评论后)
当您说这有点骇人听闻时,我完全同意。实际上,我一开始就忘了提到这一点。问题是,当延迟加载碰巧被不知道代码用途的人激活时,整个机制就会崩溃。我不喜欢以不明显的方式依赖于状态的代码。所以我总是更喜欢第一种方法。

于 2012-12-16T19:39:09.080 回答
2

通常这是使用获取实体时加载的导航属性来完成的。

但是,您也可以使用以下方法执行此操作:

(from d in baga.Locations
 from l in Lodgings
 where (d.LocationID == l.destination_id)
 where (d.Country = 'usa' && (l.MilesFromNearestAirport > 5 || l.MilesFromNearestAirport == null))
 select d)
 .ToList();

我希望这对你有帮助。

于 2012-12-16T17:06:44.197 回答
1

使用 LINQ 连接怎么样?

 var res = from d in context.Destinations
           join l in context.Lodgings on d.LocationID equals l.destination_id
           where (l.MilesFromNearestAirport > 5 || l.MilesFromNearestAirport == null)
                 && d.Country = "usa"
           select new {
                     Destination = d,
                     Location = l
                  }
于 2012-12-17T08:22:04.017 回答