2012-03-02 45 views
1

我在SQL下表:LINQ到实体 - 随着多对多的关系 - VB.NET

用户(用户名,电子邮件) 角色(角色ID,角色名) UsersInRoles(用户ID,角色ID)

我想带回一个所有角色列表和一个字段,说明该角色是否已分配给特定用户。

在SQL我会用下面的查询实现这个目标:

SELECT R.RoleID, RoleName, CASE WHEN ISNULL(UIR.UserID, 0) = 0 THEN 0 ELSE 1 END 
FROM Roles R 
LEFT JOIN UsersInRoles UIR ON R.RoleID = UIR.RoleID AND UserID = 2 

我的实体模型隐藏UsersInRoles表,而是建立在每一个用户和角色的实体将两者结合起来的导航属性。

我想写一个类似的LINQ到实体查询,但一直未能。

你能帮忙吗?

回答

0

你试图执行的是LINQ的外连接。

您可以在这里找到一个例子:
http://www.hookedonlinq.com/OuterJoinSample.ashx

这里是你会怎么做你的情况:

var query = from r in db.Roles 
      from u in db.Users 
      join uir in u.Roles on r.RoleID equals uir.RoleID into outer 
      from o in outer.DefaultIfEmpty() 
      where u.UserID == 2 
      select new 
      { 
       RoleID = r.RoleID, 
       RoleName = r.RoleName, 
       IsInRole = (o != null) 
      } 

UPDATE

  • 查询
  • 修正错误
+0

我试过在VB.NET,但没有运气... – user1244893 2012-03-02 14:30:53

0

可以使用Enumerable.Select方法项目角色的列表为anonymous types包含的字段你感兴趣:

Dim results = roles.Select(Function(r) New With _ 
    { _ 
     .Id = r.RoleId, _ 
     .Name = r.RoleName, _ 
     .IsAssigned = r.Users.Any(Function(u) u.UserId = 2) _ 
    } 

如果你想避免子查询,你可以表达左外连接在LINQ:

Dim results = From r In roles 
       Group Join u In users On r.RoleId Equals u.RoleId 
       Into assignedUsers = Group _ 
       From au In assignedUsers.DefaultIfEmpty() 
       Select New With _ 
       { _ 
        .Id = r.RoleId, _ 
        .Name = r.RoleName, _ 
        .IsAssigned = If(au Is Nothing, False, au.UserId = 2) _ 
       } 
+0

的伟大工程复制此,但是这会为每个角色执行的子查询。 – ntziolis 2012-03-02 11:22:35

+0

@ntziolis确定吗?有时Entity Framework足够聪明,可以将这些LINQ表达式转换为SQL连接。尝试使用诸如SQL Profiler或[Entity Framework Profiler](http://efprof.com)之类的东西来分析您的应用程序。 – 2012-03-02 11:28:37

+0

只是再次通过LINQPad进行检查,结果SQL使用'EXISTS'子查询如预期 – ntziolis 2012-03-02 11:39:28