我正在使用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();
有什么想法吗?
答案 0 :(得分: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执行了关系修复。 (禁用延迟加载,因为延迟加载将完全加载导航属性)。
修改(在您的评论之后)
当你说它有点像黑客时,我完全同意。实际上,我首先忘了提到它。问题是当延迟加载碰巧被不知道代码是什么的人激活时,整个机制崩溃了。我不喜欢以不明显的方式依赖于状态的代码。所以我总是喜欢第一种方法。
答案 1 :(得分: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();
我希望这会对你有所帮助。
答案 2 :(得分:1)
如何使用LINQ join?
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
}