Шаблон репозитория с асинхронным - PullRequest
1 голос
/ 14 июля 2020

Я написал этот код в своем репозитории

Task<bool> UpdateUserAsync(User user);

Но я не знаю, как написать дополнительный код в классе реализатора. Этот код получает информацию пользователя и редактирует ее в базе данных. метод должен быть Asyn c

Ответы [ 2 ]

0 голосов
/ 15 июля 2020

Ваша проблема в части asyn c или в части «выборка и обновление пользователя»?

Части, связанные с «выборкой и обновлением пользователя», трудно описать, если вы не скажете нам метод, который вы используете для доступа к базе данных: используете ли вы структуру сущностей? SQL?

SQL, DbConnection, DbCommand

Предположим, у вас уже есть синхронные методы:

public User FetchUserById(int userId) {...}
private void UpdateExistingUser(User user) {...}

Вам нужно будет создать аналогичный asyn c методы:

public Task<User> FetchUserByIdAsync(int userId);
private Task UpdateExistingUserAsync(User user);

Если вы используете SQL, вы, вероятно, будете использовать класс DbCommand и методы ExecuteReader и ExecuteNonQuery. Для ваших методов asyn c используйте аналогичные методы asyn c.

Примечание: чтобы использовать DisposeAsyn c, вам потребуется C# 8. В противном случае используйте try ... finally и вызовите DisposeAsyn c явно

private async dbConnection CreateFetchUserCommand(
    DbConnection Connection,
    int userId)
{
    var dbCommand = connection.CreateCommand();
    dbCommand.CommandText = ...
    var dbParameter = dbCommand.CreateParameter();
    ... // etc.
    return dbCommand;
}

private async DbCommand CreateUpdateUserCommand(DbConnection connection, User user)
{
    var dbCommand = connection.CreateCommand();
    dbCommand.CommandText = ...
    var dbParameter = dbCommand.CreateParameter();
    ... // etc.
    return dbCommand;
}

public Task<User> FetchUserByIdAsync(int userId)
{
    using (var dbConnection = new DbConnection(...))
    {
        await dbConnection.OpenAsync();
        using (var dbCommand = dbConnection.CreateFetchUserCommand(dbConnection, userId))
        {
            using (var dataReader = await dbCommand.ExecuteReaderAsync())
            {
                 // use async methods to access fetched data
                 User user = await ...
                 return user;
            }
        }
    }
}

Аналогично: добавьте UpdateExistingUserAsyn c, который похож на ваш существующий UpdateUser.

public UpdateUser(User user)
{
    // TODO: exception if user null

    User existingUser = await FetchUserById(user.Id);
    if (existingUser == null)
    {
        // user does not exist
    }
    else
    {
        ... // copy values from user to existingUser
        await UpdateExistingUserAsync(existingUser); 
    }
}

Копирование от пользователя к existingUser позволяет обновлять только значения что вы предоставили. если вы всегда хотите обновить пользователя целиком, то FetchUserById не нужен.

Entity Framework

using (var dbConext = new MyDbContext(...))
{
    User existingUser = await dbConnection.Users.FindAsync(user.Id)
    if (existingUser != null)
    {
        ... // copy values from user to existingUser
        await dbContext.SaveAsync();
}
0 голосов
/ 14 июля 2020

Я не совсем уверен, что вы хотите сделать, опубликуйте свой код, и вы, возможно, получите лучший ответ, но если вы спрашиваете, как написать асинхронный c метод, тогда это довольно просто и чисто.

Если ваш «Репозиторий», на который вы ссылаетесь, является интерфейсом, и вы спрашиваете, как написать свою реализацию asyn c, тогда вы захотите сделать что-то вроде этого:

public async Task<bool> UpdateUserAsync(User user){
  // Check the user exists
  var existingUser = await GetUserAsync(user.Id);

  if (existingUser == null) {
    return false;
  }

  var success = await DoMySaveTransactions(); // This would be where you commit to your chosen backend.
  return success;
}

Если вы спрашиваете, как использовать ваш новый репозиторий, вы должны использовать что-то вроде следующего внутри метода, который украшен asyn c.

async void UpdateUsername(User existingUser, string newUsername) {
  existingUser.username = newUsername;
  var success = await _myRepository.UpdateUserAsync(existingUser);

  // Do something with success.
}

Если вы хотите использовать реализацию в не асинхронный c метод, тогда ваш код будет примерно таким ...


void UpdateUsername(User existingUser, string newUsername) {
  existingUser.username = newUsername;
  var success = myRepository.UpdateUserAsync(existingUser).GetAwaiter().GetResult();

  // Do something with success.
}

Если я неправильно понял, что вы хотите сделать, пожалуйста, добавьте еще пояснение.

...