从Dapper QueryMultiple中的第一个选择访问结果(多对多)

时间:2019-04-14 16:10:59

标签: c# .net dapper

我正在尝试将多对多关系映射到具有角色列表的用户

我尝试做这个问题Dapper Many-to-Many Query,但这给了我多个用户,每个用户只有一个角色。

相反,我正在尝试使用QueryMultiple语句。我的问题是,我正在从电子邮件中查询用户,但需要从用户的ID中查询角色。因此,我需要访问第一个查询语句的结果以将ID传递给第二个。我该怎么办?

        public async Task<User> GetUserByEmailAsync(string email, CancellationToken cancellationToken)
    {
        cancellationToken.ThrowIfCancellationRequested();

        using (var connection = new SqlConnection(_options.ConnectionString))
        {
            await connection.OpenAsync(cancellationToken);
            var results = await connection.QueryMultipleAsync(@"SELECT * FROM [User] WHERE Email = @email; " +
            "SELECT Id, Name, NormalizedName FROM [Role] JOIN [UserRole] ON [Role].Id = UserRole.RoleId" +
            " WHERE [UserRole].UserId = 2",  // <-- NEED TO INSERT USER ID DYNAMICALLY HERE
            new
            {
                email
            });

            var user = await results.ReadSingleAsync<User>();
            var roles = await results.ReadAsync<Role>();

            foreach (var role in roles)
            {
                user.Roles.Add(role);
            }

            return user;
        }
    }

1 个答案:

答案 0 :(得分:3)

目前无法完全测试它,但是您可以使用此方法来填充特定用户的所有角色,从而获得一个用户。

public async Task<User> UserFromEmail(string email)
{
    Dictionary<int, User> result = new Dictionary<int, User>();

    string query = @"
            SELECT u.*, r.*
            FROM [User] u JOIN [UserRole] ur on u.UserId = ur.UserId
                          JOIN [Roles] r on ur.RoleId = r.Id
            WHERE u.Email = @email;";
    using (IDbConnection cnn = OpenConnection())
    {
        var users = await cnn.QueryAsync<User, Role, User>(query, (u, r) =>
        {
            // this lambda is called for each record retrieved by Dapper
            // receiving a user and a role created by Dapper from the record
            // and it is expected to return a user.
            // We look if the user passed in is already in the dictionary 
            // and add the role received to the roles list of that user
            if (!result.ContainsKey(u.UserId))
                result.Add(u.UserId, u);
            User working = result[u.UserId];
            working.roles.Add(r);
            return u;
        }, new { email }, splitOn: "RoleId");

        // Return the first element in the dictionary
        if (result.Values.Count > 0)
            return result.Values.First();
        else
            return null;
    }
}