MVC 6 acción asincrónica

asp.net-mvc asynchronous c# dapper

Pregunta

Así que comencé mi prueba de concepto para convertir mi sitio web nHibernate en el uso de Dapper.

Mi método de acción que estoy trabajando parece estar funcionando ahora mismo:

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);
}

Pero luego me di cuenta / recordé que, para que sea asincrónico, necesito tener Task en la acción, así:

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);
}

Pero tan pronto como lo hago, me dice que necesito esperar algo. En todos los ejemplos que he visto, solo muestra algo como esto:

var result = await repo.Get(param);

Pero ya estoy haciendo la "espera" en mis repositorios.

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;
    }
}

Por lo tanto, el objetivo de cambiar a asíncrono es poder hacer ambas llamadas de forma asíncrona, luego fusionar los resultados al volver.

¿Cómo cambio la acción de mi controlador para hacer esto de forma asíncrona, mientras tengo la Task<IActionResult> ? Me gusta esto:

public Task<IActionResult>About() {}

Actualización: ¿es esto correcto entonces?

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);
}

¿Esto hará ambas llamadas de repositorio de forma asincrónica (en paralelo)?

Respuesta aceptada

También debes esperar en tu controlador. Regla de oro: nunca digas .Result , en vez de decir await .

También debe declarar su método de acción como public async también.

Actualización: esa sería la forma correcta de llamar asincrónicamente a sus repositorios. Las llamadas a la base de datos deben realizarse en paralelo porque ambas tareas se inician antes de que se espere algo. Siempre puede ver esto usted mismo al poner el registro de depuración al inicio y al final de sus métodos DB y ver que obtiene "start 1 start 2 end 1 end 2" o algo similar en lugar de "start 1 end 1 start 2 end 2" tus consultas son razonablemente lentas



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué