2009-04-27 33 views
44

如果我使用join()方法,包括()方法不再工作,如:LINQ到实体 - 包括不加载

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没有加载

没有加盟,包括()的作品

+0

你为什么这么认为?你在执行后有没有值? – pocheptsov 2009-04-27 16:50:17

+0

我猜测“属性”不是你传递给包含的实际字符串。这意味着你已经省略了问题中最重要的部分。另外,我质疑你为什么使用连接;导航属性通常是在Entity Framework中遍历关系的正确方法。 – 2009-04-27 17:36:55

+0

pocheptsov - 我知道属性尚未加载,因为Proeprties.IsLoaded是假的 嗨克雷格 - “属性”是正确的字符串。连接在不同的导航属性项目上。因为我有一个Item对象的属性(Collection.ID)的值,但我想要与它相关的实体。 Lee – 2009-04-27 20:36:18

回答

54

更新:其实我最近添加了另一个提示,涵盖了这一点,并提供了一个替代可能更好的解决方案。这样做是为了延缓使用include(),直到查询结束,看到这个以获取更多信息:Tip 22 - How to make include really 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 

这是实体框架称为关系修正功能的副作用。

在我的EF Tips series中查看此Tip 1了解更多信息。

0

尝试了更详细的方式来 做或多或少同样的事情 获得相同的结果,但更多的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(); } 
} 

你还会得到相同的(意外的)结果吗?

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

4

那么与“Item.Member”相关的“实体”(即导航的另一端)的导航属性的名称是什么。你应该使用这个而不是连接。例如,如果“实体”添加一个名为成员属性与1的基数和会员有一个名为很多的基数项目属性,你可以这样做:

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

我猜在属性你的模型在这里,但这应该给你一个总的想法。 在大多数情况下,在LINQ to Entities中使用联接是错误的,因为它表明您的导航属性设置不正确,或者您没有使用它们。

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

所以,我知道我迟到了这里的聚会,但我想我会加入我的发现。这应该是对亚历克斯詹姆斯的帖子的评论,但是因为我没有名气,所以不得不去这里。

所以我的答案是:它似乎并不像你打算的那样工作。亚历克斯詹姆斯给出了两个有趣的解决方案,但是如果你尝试它们并检查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!