c# - MVC 6 异步操作

标签 c# asp.net-mvc asynchronous dapper

所以我开始了将我的 nHibernate 网站转换为使用 Dapper 的概念验证。

我正在使用的操作方法现在似乎正在运行:

public IActionResult About()
{
    ViewData["Message"] = "Your application description page.";

    var invoice = invoiceRepo.GetInvoiceAsync(19992031);
    var allInvoices = invoiceRepo.GetAllInvoicesAsync();

    var model = new Models.AboutModel
    {
        Invoice = invoice.Result,
        AllInvoices = allInvoices.Result
    };

    return View(model);
}

但后来我意识到/记得,为了使其异步,我需要 Task在 Action 上,像这样:

public Task<IActionResult> About()
{
    ViewData["Message"] = "Your application description page.";

    var invoice = invoiceRepo.GetInvoiceAsync(19992031);
    var allInvoices = invoiceRepo.GetAllInvoicesAsync();

    var model = new Models.AboutModel
    {
        Invoice = invoice.Result,
        AllInvoices = allInvoices.Result
    };

    return View(model);
}

但是一旦我这样做,它就会告诉我需要等待一些事情。在我见过的所有示例中,它只是显示如下内容:

var result = await repo.Get(param);

但我已经在我的存储库中进行“等待”了。

public async Task<Invoice> GetInvoiceAsync(int invoiceId)
{
    const string query = "select InvoiceId, Name [InvoiceName] from dbo.Invoice where InvoiceId = @invoiceId";

    using (var conn = GetConnection())
    {
        var dp = new DynamicParameters();
        dp.Add("@invoiceId", invoiceId);

        await conn.OpenAsync();
        var invoiceResult = await conn.QueryAsync<Invoice>(query, dp, null, 30, CommandType.Text);
        var invoice = invoiceResult.SingleOrDefault();

        return invoice;
    }
}

public async Task<List<Invoice>> GetAllInvoicesAsync()
{
    const string query = "select InvoiceId, Name [InvoiceName] from dbo.Invoice where SalesPeriodId >= 17";

    using (var conn = GetConnection())
    {
        await conn.OpenAsync();
        var invoiceResult = await conn.QueryAsync<Invoice>(query, null, null, 30, CommandType.Text);
        var invoices = invoiceResult.Take(1000).ToList();

        return invoices;
    }
}

所以我切换到异步的全部意义在于能够异步执行我的两个调用,然后在返回时将结果合并在一起。

如何更改我的 Controller 操作以异步执行此操作,同时拥有 Task<IActionResult> ?像这样:

public Task<IActionResult>About() {}

更新:那么这是正确的吗?

public async Task<IActionResult> About()
{
    ViewData["Message"] = "Your application description page.";

    var invoice = invoiceRepo.GetInvoiceAsync(19992031);
    var allInvoices = invoiceRepo.GetAllInvoicesAsync();

    var model = new Models.AboutModel
    {
        Invoice = await invoice,
        AllInvoices = await allInvoices
    };

    return View(model);
}

这会异步(并行)执行两个 repo 调用吗?

最佳答案

你也需要在你的 Controller 中等待。经验法则:永远不要说 .Result,而是说 await

您还应该将您的操作方法声明为 public async

更新:那将是异步调用存储库的正确方法。数据库调用应该并行发生,因为两个任务都在等待任何事情之前开始。您总是可以自己看到这一点,方法是将调试日志记录放在数据库方法的开头和结尾,并看到您得到“start 1 start 2 end 1 end 2”或类似的东西而不是“start 1 end 1 start 2 end 2”如果您的查询相当慢。

关于c# - MVC 6 异步操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35612294/

相关文章:

c# - HttpClient.SendAsync 使用线程池而不是异步 IO?

c# - 从 DataTable 填充 ListView

ASP.Net MVC 3 应用程序在应用程序池回收时随机失败

ajax - 如何使用 ajax 和表单数据将验证码提交给 Controller

asp.net-mvc - 如何使用 Windsor 将依赖项注入(inject)到 ActionFilterAttributes 中

javascript - 如何使用node.js、ajax 和mysql 处理异步编程中的方法?

c# - 在 BeginInvoke() 中调用异步方法是否会产生 'new' 线程?

c# - C# 中的某些内容可以在运行时更改 float 比较行为吗? [x64]

c# - 在 .NET Core 应用程序中使用 LTTng 事件

javascript - 将代码迁移到 html 和 javascript 后如何引用包