Как я могу превратить синхронную структуру в асинхронную на ASP.NET CORE - PullRequest
0 голосов
/ 14 февраля 2019

У меня есть древовидный слой классов, чтобы получать данные из базы данных и обслуживать их в действии.Я получаю данные из базы данных старым способом, используя SqlParameter классы.

Мне нужно / я хочу перестроить эти методы в асинхронные методы.Что я действительно хочу, так это научиться делать эти синхронные методы асинхронными.И заставить их работать в разных потоках и использовать их во всем приложении.

Чего я не хочу, так это использовать Ado.Net или использовать готовые методы, такие как HttpClient.GetAsync

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

Моя старая структура похожачто:

Мое действие в Моем BlockController:

public ActionResult Index()
{
    return View(new BlockDb().Select());
}

Метод Select в BlockDb Класс:

    public List<Block> Select()
        {
            SqlDataReader dr = DbJobs.ExecuteReader("BlockSelect");
            List<Block> list = new List<Block>();
            Block cs;
            while (dr.Read())
            {
                cs = new Block();
                cs.ID = Convert.ToInt32(dr["ID"]);
                cs.Name= Convert.ToString(dr["Name"]);
                cs.Dt = Convert.ToDateTime(dr["Dt"]);
                cs.Ok = Convert.ToBoolean(dr["Ok"]);
                list.Add(cs);
            }

            dr.Close();
            dr.Dispose();
            return list;
        }

И последний ExecuteReader Метод в DbJobs статический класс:

    public static SqlDataReader ExecuteReader(string ProcName, params SqlParameter[] prmtr)
    {
        SqlDataReader Result = null;
        SqlConnection connect = new SqlConnection(cnn);
        try
        {
            SqlCommand command = new SqlCommand(ProcName, connect);
            command.CommandType = CommandType.StoredProcedure;

            foreach (SqlParameter item in prmtr)
                command.Parameters.Add(item);

            if (connect.State == ConnectionState.Closed)
                connect.Open();

            Result = command.ExecuteReader(CommandBehavior.CloseConnection);
            //connect.Close();
            //connect.Dispose();
        }
        catch { }

        return Result;
    }

Не могу быть уверен, что результат действия может быть таким:

public async Task<ActionResult> Index()
{
    return View(await new BlockDb().SelectAsync());
}

Как мне этого достичь?

1 Ответ

0 голосов
/ 14 февраля 2019

Чтобы преобразовать код в асинхронный, лучше всего начать с самого низкого уровня и идти вверх.Итак, начиная с DbJobs, измените каждый метод на его асинхронный эквивалент и await результат:

public static SqlDataReader ExecuteReader(string ProcName, params SqlParameter[] prmtr)
{
  SqlDataReader Result = null;
  SqlConnection connect = new SqlConnection(cnn);
  try
  {
    SqlCommand command = new SqlCommand(ProcName, connect);
    command.CommandType = CommandType.StoredProcedure;

    foreach (SqlParameter item in prmtr)
      command.Parameters.Add(item);

    if (connect.State == ConnectionState.Closed)
      await connect.OpenAsync(CancellationToken.None);

    Result = await command.ExecuteReaderAsync(CommandBehavior.CloseConnection);
  }
  catch { }

  return Result;
}

Это даст вам ошибку компилятора, сообщающую вам об изменении подписи DbJobs.ExecuteReader.Итак, если вы сделаете то, что говорит ошибка компилятора, вы получите:

public static async Task<SqlDataReader> ExecuteReaderAsync(string ProcName, params SqlParameter[] prmtr)

Теперь вы получите ошибки компилятора для всего старого кода, который вызывал DbJobs.ExecuteReader, например:BlockDb.Select.Поэтому измените их на использование асинхронных методов:

public List<Block> Select()
{
  SqlDataReader dr = await DbJobs.ExecuteReaderAsync("BlockSelect");
  List<Block> list = new List<Block>();
  Block cs;
  while (await dr.ReadAsync(CancellationToken.None))
  {
    cs = new Block();
    cs.ID = Convert.ToInt32(dr["ID"]);
    cs.Name= Convert.ToString(dr["Name"]);
    cs.Dt = Convert.ToDateTime(dr["Dt"]);
    cs.Ok = Convert.ToBoolean(dr["Ok"]);
    list.Add(cs);
  }

  dr.Close();
  dr.Dispose();
  return list;
}

Опять вы получите ошибку компилятора, сообщающую, как изменить BlockDb.Select:

public async Task<List<Block>> SelectAsync()

И, наконец,вы сделаете то же самое для Index:

public async Task<ActionResult> Index()
{
  return View(await new BlockDb().SelectAsync());
}
...