Dapper Many-to-Many Query

家住魔仙堡 提交于 2019-12-01 17:02:27

问题


I am trying to write a query to get a user in the system with all of his/her roles. There is a many-to-many relationship between users and roles. The joiner table is SystemUserUserRole with columns UserId and RoleId. My models are below:

SystemUser Model

[Key]
public int UserId { get; set; }

[Required]
[MaxLength(75)]
public string FirstName { get; set; }

[Required]
[MaxLength(75)]
public string LastName { get; set; }

[Required]
[MaxLength(15)]
public string Phone { get; set; }

[Required]
[MaxLength(250)]
public string Email { get; set; }

public virtual List<UserRole> UserRoles { get; set; }

UserRole Model

[Key]
public int RoleId { get; set; }

[Required]
[MaxLength(250)]
public string RoleName { get; set; }

public virtual List<SystemUser> SystemUsers { get; set; }

I am trying to do something below with no luck. Any suggestions on what I am doing wrong.

string query = "SELECT u.*, r.* FROM SystemUser u INNER JOIN SystemUserUserRole ur ON u.UserId = ur.UserId INNER JOIN UserRole r on ur.RoleId = r.RoleId WHERE Email = @email AND IsActive = true;";

SystemUser user = con.Query<SystemUser, UserRole, SystemUser>(query, (SystemUser, UserRole) => { SystemUser.UserRoles = UserRole; return SystemUser; }).First();

回答1:


This will work:

In the SystemUser class, add a constructor that initialises the list:

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

Then tell Dapper that for each joined row, the UserRole should be added to the SystemUser.UserRoles:

SystemUser user = con.Query<SystemUser, UserRole, SystemUser>(query,
    (SystemUser, UserRole) =>
    {
        SystemUser.UserRoles.Add(UserRole);
        return SystemUser;
    },
    splitOn: "RoleId").First();

Note that the final piece is adding the splitOn parameter, because Dapper expects identity columns to be named Id, otherwise you need to tell it the column name explicitly.




回答2:


Here is what I ended up doing... feel free to comment or post a better solution if there is one.

I had to do three separate queries. I first grabbed the user object.

SystemUser user = con.Query<SystemUser>("SELECT * FROM SystemUser WHERE Email = @email AND IsActive = true", new { email = email }).First();

I then grabbed the RoleIds from the joiner table:

IEnumerable<int> roleIds = con.Query<int>("SELECT RoleId FROM SystemUserUserRole WHERE UserId = @userId", new { userId = user.UserId });

Finally, I updated the user object and pulled all of the roles associated to that user:

user.UserRoles = con.Query<UserRole>("SELECT * FROM UserRole WHERE RoleID IN @roleIds", new { roleIds = roleIds }).ToList();



回答3:


you can also try this which worked for me:

var result = con.Query<User, Role, User>(query, (u, r) => 
                    { 
                        u.UserRoles.Add(new UserRole{ User = u, Role=r }); 
                        return u; 
                    }, splitOn:"RoleId");


来源:https://stackoverflow.com/questions/29610051/dapper-many-to-many-query

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!