Доступ к результату первого выбора в Dapper QueryMultiple (многие ко многим) - PullRequest
2 голосов
/ 14 апреля 2019

Я пытаюсь отобразить отношение «многие ко многим» в пользователя со списком ролей

Я пытался ответить на этот вопрос Сильный запрос «многие ко многим» , но он дал мне несколько пользователей с одной ролью каждый.

Вместо этого я пытаюсь использовать оператор QueryMultiple. Моя проблема заключается в том, что я запрашиваю пользователя по электронной почте, но мне нужно запросить роль из идентификатора пользователя. Поэтому мне нужно получить доступ к результату первого оператора запроса для передачи идентификатора второму. Как я могу это сделать?

        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 Ответ

3 голосов
/ 14 апреля 2019

В настоящее время не удается полностью протестировать его, но вы можете использовать этот подход, чтобы заполнить все роли для конкретного пользователя, получив в результате одного пользователя.

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;
    }
}
...