簡體   English   中英

包含存儲過程的異步方法

[英]Asynchronous method containing Stored Procedure

在我的控制器中, [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(); 避免並發的正確方法? 它有什么作用嗎? 有沒有更好的方法來實現這一目標,或者這是否足夠好?

異步與並發無關。 事實上,如果有的話,它會增加並發問題,因為異步操作沒有定義的順序,因此是“異步的”。 但是,在像 Web 應用程序這樣的多線程環境中,並發性是一個問題,無論是同步還是異步,因為 1000 個左右的線程中的每一個都可以同時執行相同的工作。

處理並發只有兩種真正的方法:鎖和並發令牌。 並發令牌是最好的方法,但它們只適用於現有的東西(而不是插入)。 基本上,您有一列存儲並發令牌,每次在該行上進行操作時,都會更新令牌。 然后,在您實際執行操作之前,您檢查令牌是否與您首先獲得該行時相同(意味着沒有任何更改)。 如果是這樣,那么您可以繼續操作。 如果沒有,那么其他東西已經修改了它,因此,繼續下去不再安全。 此檢查是通過 where 子句完成的。 例如:

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

如果Version的令牌不再相同,那么顯然沒有行將匹配並且沒有任何更新。 然后您可以使用返回的操作計數(即零)來確定存在並發故障並恢復。

這不適用於插入,因為沒有任何東西可以確定是否發生了更改。 (您不能在插入中使用 where 子句。)對於這種情況,您別無選擇,只能使用鎖來防止在執行操作時發生任何其他事情。 但是,鎖絕對會扼殺您的吞吐量,因為它本質上會強制后續請求排隊,並且一次只能處理一個。 因此,當並發​​是一個問題時,您應該完全避免這些類型的操作。 (不相互沖突的插入是好的。)

首先,異步不是並發或多線程,而是提高了吞吐量。 你是想解決並發還是吞吐量? 吞吐量意味着許多請求調用該進程而無需等待另一個請求完成。 並發意味着讓多個工作線程(線程)並發運行以完成一個進程。 查看您的示例,您不需要多個線程,因為該進程不受處理器限制但 I/O 受限制,因此單線程異步操作就可以了

如果你希望你的代碼是異步的“await command.ExecuteNonQueryAsync();” 正確,因為您正在執行 I/O 操作,並且在 I/O 操作完成之前它不會保留線程。 一旦它點擊“await command.ExecuteNonQueryAsync();” 它會將線程釋放給調用者,一旦操作完成,它就會返回之前執行的線程的控制權。

請在這里找到一個很好的答案,

異步編程和多線程有什么區別? 和一篇優秀的文章https://exceptionnotfound.net/async-await-in-asp-net-csharp-ultimate-guide/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM