简体   繁体   English

Linq到实体-Include()方法未加载

[英]Linq-to-entities - Include() method not loading

If I use a join, the Include() method is no longer working, eg: 如果我使用联接,则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 is not loaded e.Properties未加载

Without the join, the Include() works 没有联接,Include()起作用

Lee 背风处

UPDATE: Actually I recently added another Tip that covers this, and provides an alternate probably better solution. 更新:实际上,我最近添加了另一个涵盖此内容的技巧,并提供了另一种可能更好的解决方案。 The idea is to delay the use of Include() until the end of the query, see this for more information: Tip 22 - How to make include really include 想法是将Include()的使用延迟到查询结束,有关更多信息,请参见此: 技巧22-如何使include真正包含


There is known limitation in the Entity Framework when using Include(). 使用Include()时,实体框架中存在已知限制。 Certain operations are just not supported with Include. 包括只是不支持某些操作。

Looks like you may have run into one on those limitations, to work around this you should try something like this: 看起来您可能已经遇到了这些限制,要解决此问题,您应该尝试执行以下操作:

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

This will bring back the Properties, and if the relationship between entity and Properties is a one to many (but not a many to many) you will find that each resulting anonymous type has the same values in: 这将带回属性,如果实体和属性之间的关系是一对多(但不是一对多),则您将发现每个结果匿名类型在以下项中具有相同的值:

anonType.Entity.Properties
anonType.Properties

This is a side-effect of a feature in the Entity Framework called relationship fixup. 这是实体框架中称为关系修复的功能的副作用。

See this Tip 1 in my EF Tips series for more information. 有关更多信息,请参阅我的EF技巧系列中的技巧1

Try this: 尝试这个:

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

So what is the name of the navigation property on "Entity" which relates to "Item.Member" (ie, is the other end of the navigation). 因此,“实体”上与“ Item.Member”相关的导航属性的名称是什么(即,导航的另一端)。 You should be using this instead of the join. 您应该使用它而不是联接。 For example, if "entity" add a property called Member with the cardinality of 1 and Member had a property called Items with a cardinality of many, you could do this: 例如,如果“实体”添加了一个基数为1的名为Member的属性,并且Member具有一个基数为许多的Items的属性,则可以执行以下操作:

from e in dc.Entities.Include("Properties")
where e.Member.Items.Any(i => i.Collection.ID == collectionID) 
select e

I'm guessing at the properties of your model here, but this should give you the general idea. 我在这里猜测您的模型的属性,但这应该可以为您提供总体思路。 In most cases, using join in LINQ to Entities is wrong , because it suggests that either your navigational properties are not set up correctly, or you are not using them. 在大多数情况下,在LINQ to Entities中使用join是错误的 ,因为这表明您的导航属性设置不正确,或者您没有使用它们。

So, I realise I am late to the party here, however I thought I'd add my findings. 因此,我意识到我在这里参加聚会迟到了,但是我想我应该补充一下自己的发现。 This should really be a comment on Alex James's post, but as I don't have the reputation it'll have to go here. 这确实应该是对Alex James帖子的评论,但是由于我没有名声,所以必须到这里。

So my answer is: it doesn't seem to work at all as you would intend. 所以我的答案是:它似乎根本不符合您的预期。 Alex James gives two interesting solutions, however if you try them and check the SQL, it's horrible. Alex James提供了两个有趣的解决方案,但是,如果您尝试它们并检查SQL,那将是可怕的。

The example I was working on is: 我正在处理的示例是:

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

This follows the simpler of the two examples. 这是两个示例中较简单的一个。 Without the include it produces the perfectly respectable sql: 如果没有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])

But with, OMG: 但是,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

Total garbage. 总垃圾。 The key point to note here is the fact that it returns the outer joined version of the table which has not been limited by status=1. 这里要注意的关键点是它返回不受status = 1限制的表的外部联接版本。

This results in the WRONG data being returned: 这导致返回WRONG数据:

Id  Id1 Name        C1  Id2 Status  ReleaseID
2   1   Hello World 1   1   2       1
2   1   Hello World 1   2   1       1

Note that the status of 2 is being returned there, despite our restriction. 请注意,尽管有我们的限制,状态2仍将返回那里。 It simply does not work. 它根本行不通。 If I have gone wrong somewhere, I would be delighted to find out, as this is making a mockery of Linq. 如果我在某个地方出错了,我将很高兴发现,因为这是对Linq的嘲弄。 I love the idea, but the execution doesn't seem to be usable at the moment. 我喜欢这个主意,但目前执行似乎不可用。


Out of curiosity, I tried the LinqToSQL dbml rather than the LinqToEntities edmx that produced the mess above: 出于好奇,我尝试使用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]

Slightly more compact - weird count clause, but overall same total FAIL. 稍微紧凑一些-奇怪的count子句,但总的总FAIL相同。

Has anybody actually ever used this stuff in a real business application? 有人真正在实际的业务应用程序中使用过这些东西吗? I'm really starting to wonder... Please tell me I've missed something obvious, as I really want to like Linq! 我真的开始想知道...请告诉我,我真的很喜欢Linq,所以我错过了一些明显的事情!

Try the more verbose way to do more or less the same thing obtain the same results, but with more 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(); }
}

Do you still get the same (unexpected) result? 您仍然得到相同(意外)的结果吗?

EDIT : Changed the first sentence, as it was incorrect. 编辑 :更改了第一句话,因为它是不正确的。 Thanks for the pointer comment! 感谢指针评论!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM