Linq到实体-未加载Include()方法
如果使用联接,Include()方法将不再工作,例如:Linq到实体-未加载Include()方法,linq,entity-framework,Linq,Entity Framework,如果使用联接,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.未加载属性 如果没有连接,Include()可以工作 Lee尝试更详细的方法来做或多或少相同的事情以获得相同的结果,但使用更多的数据调用: var mydat
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.未加载属性
如果没有连接,Include()可以工作
Lee尝试更详细的方法来做或多或少相同的事情以获得相同的结果,但使用更多的数据调用:
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(); }
}
你还得到同样的(意想不到的)结果吗
编辑:更改了第一句,因为它不正确。谢谢你的点评 那么,“实体”上与“Item.Member”(即导航的另一端)相关的导航属性的名称是什么。你应该使用这个而不是连接。例如,如果“实体”添加一个基数为1的名为Member的属性,而Member有一个基数为many的名为Items的属性,则可以执行以下操作:
from e in dc.Entities.Include("Properties")
where e.Member.Items.Any(i => i.Collection.ID == collectionID)
select e
我在这里猜测你的模型的属性,但这应该给你一个大概的想法。在大多数情况下,在LINQ to Entities中使用join是错误的,因为这表明您的导航属性设置不正确,或者您没有使用它们。更新:实际上,我最近添加了另一个技巧,涵盖了这一点,并提供了另一个可能更好的解决方案。我们的想法是将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
这是实体框架中称为关系修复的特性的副作用
有关详细信息,请参见my中的此项。尝试以下操作:
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")
var query=(ObjectQuery)(来自dc.Entities中的e)
将i加入dc。e.ID上的项目等于i.Member.ID
其中(i.Collection.ID==collectionID)
选择(e)
返回查询。包括(“属性”)
因此,我意识到我在这里的聚会迟到了,不过我想我应该补充一下我的发现。这真的应该是对亚历克斯·詹姆斯的帖子的评论,但因为我没有这个名声,所以只能在这里发表
所以我的答案是:它似乎根本不像你想的那样有效。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();
下面是两个示例中较简单的示例。如果没有include,它将生成完全受人尊敬的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])
但是,天哪:
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的状态仍将返回那里。它根本不起作用。
如果我出了什么差错,我会很高兴地发现,因为这是对林克的嘲弄。我喜欢这个主意,但目前执行起来似乎不可行
出于好奇,我尝试了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]
稍微紧凑一点-奇怪的count子句,但总体上相同,完全失败
有人在实际的商业应用程序中使用过这种东西吗?我真的开始怀疑。。。
请告诉我,我错过了一些明显的东西,因为我真的很想喜欢林克 你为什么这么认为?执行后是否为其指定值?我猜“Properties”不是要传递以包含的实际字符串。这意味着你省略了问题最重要的部分。此外,我还质疑您为什么要使用join;导航属性通常是遍历Entity Framework.pocheptsov中关系的正确方法-我知道属性没有加载,因为proeprites.IsLoaded是false,Hi Craig-“properties”是正确的字符串。联接位于不同的导航属性项上。连接之所以存在,是因为我有一个Item对象(Collection.ID)属性的值,但我需要与其相关的实体。这根本不是一回事。您的代码将导致n+1个数据库查询,其中n是检索到的行数。在1个数据库查询中包含结果。我知道我没有做同样的事情-这是一种草率的说法,说我最终会得到相同的结果。这样做的主要原因是查看是否有任何属性以这种方式加载。如果不是,则问题不可能出现在.Include()语法中,而可能出现在数据中(例如,关联的属性记录可能丢失了…)。您好,如果我使用Properties.load()加载属性,那么它确实正确加载了属性。如果我在不包含联接的查询中使用Include(“属性”),例如:从dc.Entities.Include(“属性”)中的e选择e;它工作正常。利兹:情况还是这样吗?如果使用“select new Item{…};”,.Include()语句不起作用?@grimus,当查询生成的元素类型不是实体类型时,将整个查询包装在
Include
中当前似乎不起作用。然而,最初的建议是在select
子句中获取导航属性值,这似乎仍然可以解决这个问题。