Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dapper Many-to-Many Query

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();
like image 489
Andrew Avatar asked Apr 13 '15 16:04

Andrew


People also ask

What is splitOn in Dapper?

splitOn: CustomerId will result in a null customer name. If you specify CustomerId,CustomerName as split points, dapper assumes you are trying to split up the result set into 3 objects. First starts at the beginning, second starts at CustomerId , third at CustomerName .

What is QueryMultipleAsync?

QueryMultipleAsync. This method runs multiple queries simultaneously and binds the result via a grid reader. The reader can be strongly typed in C#, which returns a list of enumerable objects. This works like QueryAsync , except it runs multiple queries.

What is the use of querymultiple in Dapper?

Dapper Tutorial Dapper - QueryMultiple. Description. QueryMultiple method is an extension method which can be called from any object of type IDbConnection. It can execute multiple queries within the same command and map results.

How to select multiple rows of data with Dapper?

Selecting Multiple Rows Of Data With Dapper Dapper provides a number of methods for selecting data, depending on how you want to work with the data that you retrieve. The Query methods link Query and Query<T> link

Is it better to use join or mapping in Dapper?

For most scenarios, executing a JOIN query is likely to be the right choice. Each record returned from a JOIN query will include data from multiple objects. Dapper provides a feature called Multi mapping to enable you to explicitly map data in a single row to multiple objects.

Is it possible to map a dapper query to a database?

According to this answer there is no one to many mapping support built into Dapper.Net. Queries will always return one object per database row. There is an alternative solution included, though. Show activity on this post. A slight modification of Andrew's answer that utilizes a Func to select the parent key instead of GetHashCode.


1 Answers

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.

like image 67
peter_raven Avatar answered Sep 25 '22 16:09

peter_raven