简体   繁体   English

实体框架深入查询多对多

[英]Entity Framework Deep Query Many to Many

New to Entity Framework, trying to figure out some stuff. 实体框架的新手,试图找出一些东西。 I have tables as listed below: 我有如下表格:

Users
---------
UserID
UserName

Roles
---------
RoleID
RoleName

UserRoles
---------
UserRoleID
UserID
RoleID

I am using a repository pattern. 我正在使用存储库模式。 here's an example of a repository (they're all essentially the same) 这是一个存储库的例子(它们都基本相同)

public class RoleRepository : IRoleRepository
{
    private AuthorizationContext context = new AuthorizationContext();
    public IQueryable<Role> Roles
    {
        get
        {
            return this.context.Roles;
        }
    }
    public bool Save(Role pRole)
    {
        if (pRole.RoleID == 0 || pRole.RoleID == null)
        {
            context.Roles.Add(pRole);
        }
        context.SaveChanges();
        return true;
    }
    public bool Delete(Role pRole)
    {
        context.Roles.Remove(pRole);
        context.SaveChanges();
        return true;
    }
}

Now, I want to test to see if a user (by UserName) belongs to a role (by RoleName). 现在,我想测试一下用户(通过UserName)是否属于某个角色(通过RoleName)。 How can I query? 我怎么查询? I expected it to be something like this, but it doesn't work: 我希望它是这样的,但它不起作用:

public bool IsUserInRole(string username, string roleName)
{
    var repo = new UserRepository();
    var user = repo.Users.FirstOrDefault(u => u.NetID == username && u.UserRoles.FirstOrDefault(r => r.Role.Name == roleName));
}

How can I query to see if the user belongs to the role? 如何查询用户是否属于该角色? I would prefer to use predicates if possible. 如果可能的话,我更愿意使用谓词。

I would use the .Any function like this: 我会使用像这样的.Any函数:

public static bool IsUserInRole(string username, string roleName)
{
  using(var roleRepository = new RoleRepository())
  {
    return roleRepository.Roles.Any(r => r.RoleName == roleName && r.UserRoles.Any(ur => ur.User.UserName == username));
  }
}

Here is a sample Console Application: 以下是控制台应用程序示例:

class Program
{
  static void Main(string[] args)
  {
    var users = new List<string> { "A", "B", "C", "D" };
    var roles = new List<string> { "User", "Admin", "Superuser"};

    //User A has roles: User, Admin, Superuser
    Debug.Assert(IsUserInRole(users[0], roles[0]) == true);
    Debug.Assert(IsUserInRole(users[0], roles[1]) == true);
    Debug.Assert(IsUserInRole(users[0], roles[2]) == true);

    //User B has roles: User, Admin
    Debug.Assert(IsUserInRole(users[1], roles[0]) == true);
    Debug.Assert(IsUserInRole(users[1], roles[1]) == true);
    Debug.Assert(IsUserInRole(users[1], roles[2]) == false);

    //User C has roles: User
    Debug.Assert(IsUserInRole(users[2], roles[0]) == true);
    Debug.Assert(IsUserInRole(users[2], roles[1]) == false);
    Debug.Assert(IsUserInRole(users[2], roles[2]) == false);

    //User D has no roles
    Debug.Assert(IsUserInRole(users[3], roles[0]) == false);
    Debug.Assert(IsUserInRole(users[3], roles[1]) == false);
    Debug.Assert(IsUserInRole(users[3], roles[2]) == false);

    Debugger.Break();
  }

  public static bool IsUserInRole(string username, string roleName)
  {
    using(var roleRepository = new RoleRepository())
    {
      return roleRepository.Roles.Any(r => r.RoleName == roleName && r.UserRoles.Any(ur => ur.User.UserName == username));
    }
  }
}

public interface IRoleRepository : IDisposable
{

}

public class RoleRepository : IRoleRepository
{
  private Context context = new Context();
  public IQueryable<Role> Roles
  {
    get
    {
      return this.context.Roles.AsQueryable<Role>();
    }
  }

  public void Dispose()
  {
      //Do nothing
  }
}

public class Context : IDisposable
{
  public IList<User> Users { get; set; }
  public IList<Role> Roles { get; set; }
  public IList<UserRole> UserRoles { get; set; }

  public Context()
  {
    //Generate Some Fake Data
    Users = new List<User>();
    Users.Add(new User { UserID = 1, UserName = "A" });
    Users.Add(new User { UserID = 2, UserName = "B" });
    Users.Add(new User { UserID = 3, UserName = "C" });
    Users.Add(new User { UserID = 4, UserName = "D" });

    Roles = new List<Role>();
    Roles.Add(new Role { RoleID = 1, RoleName = "User" });
    Roles.Add(new Role { RoleID = 2, RoleName = "Admin" });
    Roles.Add(new Role { RoleID = 3, RoleName = "Superuser" });

    UserRoles = new List<UserRole>();
    UserRoles.Add(new UserRole(1, Users[0], Roles[0]));
    UserRoles.Add(new UserRole(1, Users[0], Roles[1]));
    UserRoles.Add(new UserRole(1, Users[0], Roles[2]));
    UserRoles.Add(new UserRole(1, Users[1], Roles[0]));
    UserRoles.Add(new UserRole(1, Users[1], Roles[1]));
    UserRoles.Add(new UserRole(1, Users[2], Roles[0]));

    //User A has roles: User, Admin, Superuser
    //User B has roles: User, Admin
    //User C has roles: User
    //User D has no roles
  }

  public void Dispose()
  {
    //Do nothing
  }
}

public class User
{
  public int UserID { get; set; }
  public string UserName { get; set; }

  public IList<UserRole> UserRoles { get; set; }

  public User()
  {
    UserRoles = new List<UserRole>();
  }
}

public class Role
{
  public int RoleID { get; set; }
  public string RoleName { get; set; }

  public IList<UserRole> UserRoles { get; set; }

  public Role()
  {
    UserRoles = new List<UserRole>();
  }
}

public class UserRole
{
  public int UserRoleID { get; set; }

  public int UserId { get; set; }
  public User User { get; set; }

  public int RoleId { get; set; }
  public Role Role { get; set; }

  public UserRole(int id, User user, Role role)
  {
    UserRoleID = id;

    UserId = user.UserID;
    User = user;
    user.UserRoles.Add(this);

    RoleId = role.RoleID;
    Role = role;
    role.UserRoles.Add(this);
  }
}

Here is the modified "IsUserInRole" API that you already created : 以下是您已创建的已修改的“IsUserInRole”API:

    public bool IsUserInRole(string username, string roleName)
    {
        var repo = new UserRepository();
        return repo.Users.Any(u => u.UserName == username && u.UserRoles.Any(userrole => userrole.Role.RoleName == roleName));
    }

The problem with your API was the FirstOrDefault, which restricts the navigation properties. 您的API的问题是FirstOrDefault,它限制了导航属性。

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

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