如果我使用连接,则Include()方法不再有效,例如:
from e in dc.Entities.Include("Properties")
join i in dc.Items on e.ID equals i.Member.ID
where (i.Collection.ID == collectionID)
select e
e.Properties
未加载
没有连接,Include()可以正常工作
利
答案 0 :(得分:54)
更新:实际上我最近添加了另一个提示,涵盖了这一点,并提供了另一种可能更好的解决方案。我们的想法是延迟使用Include()直到查询结束,有关详细信息,请参阅此内容:Tip 22 - How to make include really include
使用Include()时,实体框架存在已知限制。 Include不支持某些操作。
看起来你可能遇到过这些限制的问题,为了解决这个问题你应该尝试这样的事情:
var results =
from e in dc.Entities //Notice no include
join i in dc.Items on e.ID equals i.Member.ID
where (i.Collection.ID == collectionID)
select new {Entity = e, Properties = e.Properties};
这将带回属性,如果实体和属性之间的关系是一对多(但不是多对多),您会发现每个结果匿名类型具有相同的值:
anonType.Entity.Properties
anonType.Properties
这是实体框架中一项称为关系修正的功能的副作用。
有关详细信息,请参阅我的Tip 1中的EF Tips series。
答案 1 :(得分:20)
试试这个:
var query = (ObjectQuery<Entities>)(from e in dc.Entities
join i in dc.Items on e.ID equals i.Member.ID
where (i.Collection.ID == collectionID)
select e)
return query.Include("Properties")
答案 2 :(得分:4)
那么“实体”上与“Item.Member”相关的导航属性的名称是什么(即导航的另一端)。您应该使用此而不是连接。例如,如果“entity”添加一个名为Member的属性,其基数为1,而Member有一个名为Items的属性,其基数为多,则可以这样做:
from e in dc.Entities.Include("Properties")
where e.Member.Items.Any(i => i.Collection.ID == collectionID)
select e
我在这里猜测你的模型的属性,但这应该给你一般的想法。 在大多数情况下,在LINQ to Entities中使用连接是错误的,因为它表明您的导航属性设置不正确,或者您没有使用它们。
答案 3 :(得分:1)
所以,我意识到我在这里参加派对很晚,但是我想我会加上我的发现。这应该是对亚历克斯詹姆斯的帖子的评论,但由于我没有声誉,所以必须去这里。
所以我的答案是:它似乎根本无法发挥作用。 Alex James提供了两个有趣的解决方案,但是如果你尝试它们并检查SQL,那就太可怕了。
我正在研究的例子是:
var theRelease = from release in context.Releases
where release.Name == "Hello World"
select release;
var allProductionVersions = from prodVer in context.ProductionVersions
where prodVer.Status == 1
select prodVer;
var combined = (from release in theRelease
join p in allProductionVersions on release.Id equals p.ReleaseID
select release).Include(release => release.ProductionVersions);
var allProductionsForChosenRelease = combined.ToList();
这遵循两个例子中较简单的一个。没有包含它会产生完全可敬的sql:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name]
FROM [dbo].[Releases] AS [Extent1]
INNER JOIN [dbo].[ProductionVersions] AS [Extent2] ON [Extent1].[Id] = [Extent2].[ReleaseID]
WHERE ('Hello World' = [Extent1].[Name]) AND (1 = [Extent2].[Status])
但是,OMG:
SELECT
[Project1].[Id1] AS [Id],
[Project1].[Id] AS [Id1],
[Project1].[Name] AS [Name],
[Project1].[C1] AS [C1],
[Project1].[Id2] AS [Id2],
[Project1].[Status] AS [Status],
[Project1].[ReleaseID] AS [ReleaseID]
FROM ( SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
[Extent2].[Id] AS [Id1],
[Extent3].[Id] AS [Id2],
[Extent3].[Status] AS [Status],
[Extent3].[ReleaseID] AS [ReleaseID],
CASE WHEN ([Extent3].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
FROM [dbo].[Releases] AS [Extent1]
INNER JOIN [dbo].[ProductionVersions] AS [Extent2] ON [Extent1].[Id] = [Extent2].[ReleaseID]
LEFT OUTER JOIN [dbo].[ProductionVersions] AS [Extent3] ON [Extent1].[Id] = [Extent3].[ReleaseID]
WHERE ('Hello World' = [Extent1].[Name]) AND (1 = [Extent2].[Status])
) AS [Project1]
ORDER BY [Project1].[Id1] ASC, [Project1].[Id] ASC, [Project1].[C1] ASC
垃圾总量。这里要注意的关键点是它返回表的外连接版本,该版本不受status = 1的限制。
这会导致返回错误的数据:
Id Id1 Name C1 Id2 Status ReleaseID
2 1 Hello World 1 1 2 1
2 1 Hello World 1 2 1 1
请注意,尽管我们有限制,但仍会在那里返回2的状态。它根本不起作用。 如果我在某个地方出错了,我会很高兴发现,因为这是对Linq的嘲弄。我喜欢这个想法,但目前执行似乎并不可用。
出于好奇,我尝试了LinqToSQL dbml,而不是产生上述混乱的LinqToEntities edmx:
SELECT [t0].[Id], [t0].[Name], [t2].[Id] AS [Id2], [t2].[Status], [t2].[ReleaseID], (
SELECT COUNT(*)
FROM [dbo].[ProductionVersions] AS [t3]
WHERE [t3].[ReleaseID] = [t0].[Id]
) AS [value]
FROM [dbo].[Releases] AS [t0]
INNER JOIN [dbo].[ProductionVersions] AS [t1] ON [t0].[Id] = [t1].[ReleaseID]
LEFT OUTER JOIN [dbo].[ProductionVersions] AS [t2] ON [t2].[ReleaseID] = [t0].[Id]
WHERE ([t0].[Name] = @p0) AND ([t1].[Status] = @p1)
ORDER BY [t0].[Id], [t1].[Id], [t2].[Id]
略微更紧凑 - 怪异的计数条款,但整体相同的总失败。
有没有人在真实的商业应用程序中使用过这些东西?我真的开始怀疑...... 请告诉我,我错过了一些明显的东西,因为我真的很想要Linq!
答案 4 :(得分:-1)
尝试更详细的方法或多或少做同样的事情获得相同的结果,但有更多的数据通道:
var mydata = from e in dc.Entities
join i in dc.Items
on e.ID equals i.Member.ID
where (i.Collection.ID == collectionID)
select e;
foreach (Entity ent in mydata) {
if(!ent.Properties.IsLoaded) { ent.Properties.Load(); }
}
您是否仍然得到相同(意外)的结果?
编辑:更改了第一句,因为它不正确。感谢指针评论!