Linq-to-entities – Include()方法不加载

如果我使用联接,则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()就起作用了

背风处

更新:其实我最近添加了另一个提示涵盖了这一点,并提供了一个替代可能更好的解决scheme。 这个想法是延迟使用Include()直到查询结束,查看更多信息: 提示22 – 如何使include包含真正包含


使用Include()时,entity framework中存在已知的限制。 包含某些操作不受支持。

看起来你可能已经遇到了这些限制之一,要解决这个问题,你应该尝试这样的事情:

 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}; 

这将带回属性,如果实体和属性之间的关系是一对多(但不是多对多),您会发现每个生成的匿名types在以下位置具有相同的值:

 anonType.Entity.Properties anonType.Properties 

这是entity framework中称为关系修正的function的副作用。

有关更多信息,请参阅我的EF提示系列中的 提示1 。

尝试这个:

 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") 

那么与“Item.Member”(即导航的另一端)有关的“Entity”上的导航属性的名称是什么。 你应该使用这个而不是连接。 例如,如果“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中使用连接是错误的 ,因为它表明您的导航属性设置不正确,或者您没有使用它们。

所以,我意识到我在这里参加晚会,但是我想我会补充我的发现。 这应该是对亚历克斯·詹姆斯的post的评论,但是因为我没有名气,所以不得不去这里。

所以我的答案是:它并不像你想要的那样工作。 亚历克斯·詹姆斯给出了两个有趣的解决scheme,但是如果你尝试一下并检查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 

请注意,尽pipe我们有这个限制,但是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] 

稍微更紧凑 – 奇怪的计数条款,但总体FAIL相同。

有没有人真的在实际的商业应用中使用过这些东西? 我真的开始怀疑…请告诉我,我已经错过了明显的东西,因为我真的想要Linq!

尝试更详细的方式做更多或更less的相同的事情获得相同的结果,但与更多的datacalls:

 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(); } } 

你仍然得到相同的(意外的)结果?

编辑 :改变了第一句话,因为它是不正确的。 感谢指针评论!