Асинхронный метод, содержащий хранимую процедуру - PullRequest
0 голосов
/ 09 января 2020

В моем контроллере методы [POST] обычно вызывают хранимую процедуру из базы данных. Мне интересно, правильно ли я поступаю, чтобы избежать проблем с параллелизмом. В качестве примера возьмем следующий метод:

    [HttpPost]
    public async Task<IActionResult> Create(Phase phase)
    {
        int releaseId = (int)TempData["id"];
        string connectionString = Configuration["ConnectionStrings:DefaultConnection"];
        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            string sql = "CreatePhase";

            using (SqlCommand command = new SqlCommand(sql, connection))
            {
                command.CommandType = CommandType.StoredProcedure;

                // adding parameters
                SqlParameter parameter = new SqlParameter
                {
                    ParameterName = "@Name",
                    Value = phase.Name,
                    SqlDbType = SqlDbType.VarChar,
                    Size = 50
                };
                command.Parameters.Add(parameter);

                parameter = new SqlParameter
                {
                    ParameterName = "@ReleaseId",
                    Value = releaseId,
                    SqlDbType = SqlDbType.Int
                };
                command.Parameters.Add(parameter);

                connection.Open();
                await command.ExecuteNonQueryAsync();
                connection.Close();
            }
        }

        return RedirectToAction("Index", "Phase", new { id = releaseId });
    }

Является ли await command.ExecuteNonQueryAsync(); правильным способом избежать параллелизма? Имеет ли это какое-либо влияние? Есть ли лучшие способы достижения этого или это достаточно хорошо?

Ответы [ 2 ]

1 голос
/ 09 января 2020

Asyn c не имеет ничего общего с параллелизмом. Фактически, если что-нибудь, это добавляет к проблемам параллелизма, так как нет никакого определенного порядка для операций с asyn c, следовательно, "асинхронный". Однако в многопоточной среде, такой как веб-приложение, параллелизм является проблемой, syn c или asyn c, поскольку каждый из 1000 или более потоков может выполнять одну и ту же работу одновременно.

Есть только два реальных способа обработки параллелизма: блокировки и токены параллелизма. Жетоны параллелизма являются лучшим методом, но они работают только для существующих вещей (не вставок). По сути, у вас есть столбец, в котором хранится токен параллелизма, и каждый раз, когда в этой строке выполняется операция, токен обновляется. Затем, прежде чем вы на самом деле выполните операцию, вы проверяете, что токен такой же, как когда вы получили строку в первую очередь (то есть ничего не изменилось). Если это так, то вы можете продолжить операцию. Если нет, то что-то еще изменило его, и, таким образом, уже не безопасно go впереди. Эта проверка выполняется с помощью предложения where. Например:

update Foos set Bar = 'Baz' where Id = 1 and Version = {token}

Если токен в Version больше не совпадает, то, очевидно, ни одна строка не будет соответствовать и ничего не будет обновлено. Затем вы можете использовать возвращенное число операций (т. Е. Ноль), чтобы определить, что произошел сбой параллелизма, и восстановить.

Это не будет работать со вставкой, потому что нечего отключать, чтобы определить, или не произошло изменение. (Вы не можете использовать предложение where во вставке.) В этой ситуации у вас нет другого выбора, кроме как использовать блокировки, чтобы предотвратить что-либо еще во время выполнения операции. Однако блокировки абсолютно убьют вашу пропускную способность, так как по существу вынуждают последующие запросы стоять в очереди, и они могут обрабатываться только по одному за раз. Таким образом, вы должны избегать этих типов операций полностью, когда параллелизм является проблемой. (Вставки, которые не конфликтуют друг с другом, подойдут.)

0 голосов
/ 09 января 2020

Прежде всего, асинхронность - это не параллелизм или многопоточность, а повышение пропускной способности. Вы пытаетесь решить параллелизм или пропускную способность? Пропускная способность означает, что многие запросы вызывают процесс, не дожидаясь завершения другого. Параллелизм означает одновременное выполнение нескольких рабочих процессов (потоков) для завершения процесса. Глядя на ваш пример, вам не нужны несколько потоков, так как процесс не ограничен процессором, а ограничен вводом / выводом, поэтому однопоточная асинхронная операция будет в порядке

Если вы хотите, чтобы ваш код был асинхронным, команда "await .ExecuteNonQueryAsyn c ();» исправить, как вы делаете операцию ввода-вывода, и он не будет удерживать поток, пока операция ввода-вывода не завершится. Как только он нажмет "await command.ExecuteNonQueryAsyn c ();" он освобождает поток для вызывающей стороны и после завершения операции возвращает управление потоком, который выполнялся раньше.

Пожалуйста, найдите здесь отличный ответ,

В чем разница между асинхронное программирование и многопоточность? и отличная статья https://exceptionnotfound.net/async-await-in-asp-net-csharp-ultimate-guide/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...