Как преобразовать приведенный ниже код, используемый для подключения к базе данных с помощью EF 6, в асинхронную задачу в C #? - PullRequest
0 голосов
/ 12 июня 2019

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

Я создал асинхронную задачу, и она отлично работает, вы можете обратиться к Using Async Task разделу для кода. Но я хочу переписать The existing code of the project раздел как async task, чтобы сохранить согласованность в проекте.

Использование асинхронной задачи: Приведенный ниже код работает нормально.

public static async Task<Student> InsertAsync(Student student)
{
  try
  {
    using(PracticeContext context = new PracticeContext())
    {
      Repository<Student> repository = new Repository<Student>(context);
      return await repository.InsertAsync(student);
    }
  }
  catch (Exception ex)
  {
    Console.WriteLine(ex);
    return null;
  }
}

Существующий код проекта:

Я хочу реализовать приведенный ниже код как async task для обоих методов Insert() и Execute(). Таким образом, данные будут добавлены в database без длительного удержания пользовательского интерфейса и сделают проект более удобным для пользователя.

Пожалуйста, предложите или предоставьте async implementation из приведенных ниже кодов.

public static Student Insert(Student student)
{
  try
  {
    return Execute<Student, Student>((repository) => {
      return repository.Insert(student);
    });
  }
  catch (Exception ex)
  {
    Console.WriteLine(ex);
    return null;
  }
}

private static TResult Execute<TResult, T>(Func<Repository<T>, TResult> func) where T: class
{
  using(PracticeContext context = new PracticeContext())
  {
    try
    {
      return func(new Repository<T>(context));
    }
    catch(Exception ex)
    {
      Console.WriteLine(ex);
      throw new Exception("Error Occured.");
    }
  }
}

Я был бы рад добавить больше материалов, если это необходимо, чтобы сделать вопросы более точными и понятными.

1 Ответ

2 голосов
/ 12 июня 2019

Первое, что вы сделаете, - измените вызов самого низкого уровня на использование асинхронной версии и используйте async в его включающем методе / лямбде.Тогда позвольте async расти оттуда.Таким образом, первым шагом будет:

    return Execute<Student, Student>(async (repository) => {
      return await repository.Insert(student);
    });

Этот код тогда требует Execute, чтобы разрешить асинхронных делегатов .На этом этапе мы, вероятно, хотим, чтобы другой код продолжал использовать синхронный Execute, поэтому мы можем скопировать / вставить его и заставить новую перегрузку принимать асинхронный делегат:

private static async Task<TResult> Execute<TResult, T>(Func<Repository<T>, Task<TResult>> func) where T: class
{
  using(PracticeContext context = new PracticeContext())
  {
    try
    {
      return await func(new Repository<T>(context));
    }
    catch(Exception ex)
    {
      Console.WriteLine(ex);
      throw new Exception("Error Occured.");
    }
  }
}

Теперь, когда асинхронный Execute возвращает Task<T>, затем нам нужно await вернуть его обратно в вызывающий метод:

    return await Execute<Student, Student>(async (repository) => {
      return await repository.Insert(student);
    });

, что затем делает вызывающий метод также асинхронным:

public static async Task<Student> InsertAsync(Student student)
{
  try
  {
    return await Execute<Student, Student>(async (repository) => {
      return await repository.Insert(student);
    });
  }
  catch (Exception ex)
  {
    Console.WriteLine(ex);
    return null;
  }
}
...