【问题标题】:Where to use Async Await with databases? In high-level or low-level module? [closed]在哪里使用 Async Await 和数据库?在高级或低级模块中? [关闭]
【发布时间】:2021-04-05 02:27:03
【问题描述】:

我知道我们应该在访问数据库时使用异步和等待,因为处理这个请求需要时间,我们希望程序在等待时继续执行其他任务。

但是,我不确定在哪里进行等待调用。

调用低级数据库访问模块的高级模块应该使用await,还是应该使用低级模块?

我认为它应该是高级模块,因为它有更多的事情要做???

下面是一些示例代码,使用命令的正确或错误的地方?

高级控制器模块:

public async Task<IActionResult> Delete(int id, string email)
{
    email = email.ToLower();

    IUsers user = new Users();
    
    // Async Await call here or in lower level module???
    bool del = await Task.Run(() => user.DeleteUser(id, email));                

    if (del == true)
    {
        System.Diagnostics.Debug.WriteLine(String.Format("User Deleted"));
        return Ok();
    }
    else
    {
        // If del is false or null
        System.Diagnostics.Debug.WriteLine("Error. User ID: {0} Email: {1} didn't match, not deleted. ", id, email));
        return BadRequest();
    }
}

低级数据库访问模块:

// Connection String
IDbConnection dbConnection = new MySqlConnection(@"Server=127.0.0.1;blah;");


bool IUsers.DeleteUser(int id, string email)
    {
        using (dbConnection)
        {
            try
            {
                string cmd = @"DELETE from users WHERE ID=@Id AND EMAIL=@Email";

                bool result = false;

                // Should async await maybe be here???
                var del = dbConnection.Execute(cmd, new { Id = id, Email = email });

                //Change result to True if execute command went ahead
                result = del > 0;

                // Returns True or False
                return result;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception in Users.DeleteUser");
                Console.WriteLine("Exception: {0}", ex.Message);
                return false;
            }
        }
    }

感谢您的反馈!

【问题讨论】:

  • 一旦你开始使用 async/await,你应该从底部一直使用到顶部。所以你应该让DeleteUser返回Task&lt;bool&gt;并等待,而不是Task.Run。你应该 await 一个 ExcuteAsync 方法或等效方法。
  • 我推荐阅读this question。毫无疑问,其他人可以给出比我更连贯的答案,但简而言之:对 IO 使用异步方法(例如ExecuteAsync),因为这允许在 IO 发生时暂停任务执行(释放资源以处理其他请求)。以您的方式使用 Task.Run 只是在等待 100% 同步 DB 代码执行时锁定任务使用的线程池中的线程,这意味着您总体上使事情变得更糟而不是更好。
  • 异步自上而下/自下而上就是这样。
  • 看看这个:Should I expose asynchronous wrappers for synchronous methods? 答案是否定的。这意味着如果你真的必须使用Task.Run,你应该在最后一刻使用它。

标签: c# async-await


【解决方案1】:

在大多数情况下,您根本不应该在 ASP.NET 上使用Task.Run。特别是在这种情况下,您应该绝对不要使用Task.Run,因为它只是在后台线程上运行同步代码——我称之为“假异步”。

我建议开始在最低级别使用异步,然后从那里开始。在这种情况下:

var del = await dbConnection.ExecuteAsync(cmd, new { Id = id, Email = email });

然后编译器会给你一个错误,说你应该将DeleteUser标记为async并将其返回类型更改为Task&lt;bool&gt;。您还需要更改IUsers 接口来执行此操作:

async Task<bool> IUsers.DeleteUserAsync(int id, string email)

并更新所有调用它的东西,让你的控制器方法看起来像:

bool del = await user.DeleteUserAsync(id, email);

【讨论】:

    猜你喜欢
    • 2013-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-22
    相关资源
    最近更新 更多