2010-05-14 135 views
0

以前我问过一个关于这个问题的问题,但是我的数据库结构发生了变化,虽然它使其他事情变得更简单,但现在这部分更加复杂。 Here是上一个问题。实体框架 - 多对多子查询

当时,我的EF上下文有一个UsersProjects对象,因为还有其他属性。现在我简化了表格,它只是关键点,所以我的EF上下文知道的是UsersProjects以及它们之间的M2M关系。就EF而言,没有更多的UsersProjects

所以我的目标是说“向我展示与我一起从事项目的所有用户”。

在SQL

,这会去是这样的:

SELECT * FROM Users INNER JOIN UsersProjects ON Users.ID=UsersProjects.UserID 
WHERE ProjectID IN (SELECT ProjectID FROM UsersProjects WHERE [email protected]) 

,我在EF开始是这样的:

  var myProjects = 
       (from p in edmx.Projects 
       where p.Users.Contains(edmx.Users.FirstOrDefault(u => u.Email == UserEmail)) 
       orderby p.Name 
       select p).ToList(); 

      var associatedUsers = 
       (from u in edmx.Users 
       where myProjects.Contains(?????????) 
       //where myProjects.Any(????????) 
       select u); 

关键在于找出放什么的???? ????。任何人都可以帮忙

回答

0
var me = context 
    .Users 
    .First(user => user.Email = "[email protected]"); 

// Note that there is no call to ToList() or AsEnumerable(). 
var myProjects = context 
    .Projects 
    .Where(project => project.Users.Contains(me)); 

var associatedUsers = context 
    .Users 
    .Where(user => myProjects.Any(project => user.Project.Contains(project))); 

但还有其他几种可能的解决方案。例如

var associatedUsers = myProjects 
    .SelectMany(project => project.Users) 
    .Distinct(); 

我更喜欢。

此外请注意,使用导航属性而不是使用Contains()来获得myProjects要容易得多。

var myProjects = me.Projects; 
+0

不错。有道理,所以我将它标记为答案,但是当我插入它时,我遇到了一些我必须解决的有趣错误。看到我的帖子下面... – Jorin 2010-05-15 20:07:18

0

丹尼尔,我试过你曾经遇到过的问题。你能解释这些错误是什么意思吗?

我想:

 // Doesn't work. 
     using (var edmx = new MayflyEntities()) 
     { 
      var me = edmx.Users.First(user => user.Email == UserEmail); 
      var myProjects = edmx.Projects.Where(project => project.Users.Contains(me)); 
      var associatedUsers = myProjects.SelectMany(project => project.Users).Distinct(); 
     } 

但有以下两个例外:

Unable to create a constant value of type 'DomainModel.User'. Only primitive types ('such as Int32, String, and Guid') are supported in this context.

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

所以,我搬来搬去了一些东西,这个作品好,但现在我为什么好奇?在SQL事件探查器中,它全部在一个查询中执行,为什么它显示上下文已经被处置?另外,为什么它不能使用me对象而不是lambda?

 // Works fine 
     var edmx = new MayflyEntities(); 
     var myProjects = edmx.Projects.Where(project => project.Users.Contains(edmx.Users.First(user => user.Email == UserEmail))); 
     var associatedUsers = myProjects.SelectMany(project => project.Users).Distinct(); 
+0

这是对我的疏忽。实体框架只能处理原始类型常量。而不是project.Users.Contains(我)必须使用project.Users.Any(user => user.Id == me.Id)。我不确定为什么实体框架没有将涉及实体的查询转化为涉及实体关键字的查询(但可能是由于处理了数据库生成的关键字)。例如,LINQ to SQL支持像project.Users.Contains(me)这样的查询。 – 2010-05-15 21:16:25

+0

为什么你得到的ObjectDisposedException很难说,但我相当肯定这是由于你的代码中的错误。 – 2010-05-15 21:19:53

+0

edmx.Users.Where(user => user.Email == userEmail).SelectMany(user => user.Projects)是另一个获得myProjects的建议。这可以避免将lambda表达式嵌入深度三层,在我看来,它更具可读性。 – 2010-05-15 21:28:44