Saltar al contenido

Entity Framework SaveChanges() frente a SaveChangesAsync() y Find() frente a FindAsync()

Es importante comprender el código correctamente antes de adaptarlo a tu trabajo si tquieres aportar algo puedes comentarlo.

Solución:

Cada vez que necesita realizar una acción en un servidor remoto, su programa genera la solicitud, la envía y luego espera una respuesta. usaré SaveChanges() y SaveChangesAsync() como un ejemplo, pero lo mismo se aplica a Find() y FindAsync().

Di que tienes una lista myList de más de 100 artículos que necesita agregar a su base de datos. Para insertar eso, su función se vería así:

using(var context = new MyEDM())

    context.MyTable.AddRange(myList);
    context.SaveChanges();

Primero creas una instancia de MyEDMagrega la lista myList a la mesa MyTableluego llame SaveChanges() para persistir los cambios en la base de datos. Funciona como usted quiere, los registros se confirman, pero su programa no puede hacer nada más hasta que finaliza la confirmación. Esto puede tomar mucho tiempo dependiendo de lo que estés cometiendo. Si está confirmando cambios en los registros, la entidad tiene que confirmarlos uno a la vez (¡una vez tuve que guardar 2 minutos para las actualizaciones)!

Para resolver este problema, puede hacer una de dos cosas. La primera es que puede iniciar un nuevo subproceso para manejar la inserción. Si bien esto liberará el subproceso de llamada para continuar ejecutándose, creó un nuevo subproceso que simplemente se quedará allí y esperará. No hay necesidad de esa sobrecarga, y esto es lo que el async await patrón resuelve.

Para operaciones de E/S, await rápidamente se convierte en tu mejor amigo. Tomando la sección de código de arriba, podemos modificarla para que sea:

using(var context = new MyEDM())

    Console.WriteLine("Save Starting");
    context.MyTable.AddRange(myList);
    await context.SaveChangesAsync();
    Console.WriteLine("Save Complete");

Es un cambio muy pequeño, pero tiene efectos profundos en la eficiencia y el rendimiento de su código. ¿Así que lo que pasa? El comienzo del código es el mismo, creas una instancia de MyEDM y agrega tu myList para MyTable. Pero cuando llamas await context.SaveChangesAsync()la ejecución del código vuelve a la función de llamada! Entonces, mientras espera que se confirmen todos esos registros, su código puede continuar ejecutándose. Digamos que la función que contenía el código anterior tenía la firma de public async Task SaveRecords(List saveList)la función de llamada podría verse así:

public async Task MyCallingFunction()

    Console.WriteLine("Function Starting");
    Task saveTask = SaveRecords(GenerateNewRecords());

    for(int i = 0; i < 1000; i++)
        Console.WriteLine("Continuing to execute!");
    

    await saveTask;
    Console.Log("Function Complete");

No sé por qué tendría una función como esta, pero lo que genera muestra cómo async await obras. Primero repasemos lo que sucede.

La ejecución entra MyCallingFunction, Function Starting luego Save Starting se escribe en la consola, entonces la función SaveChangesAsync() se llama En este punto, la ejecución vuelve a MyCallingFunction e ingresa al bucle for escribiendo 'Continuing to Execute' hasta 1000 veces. Cuándo SaveChangesAsync() termina, la ejecución vuelve a la SaveRecordsfunción, escritura Save Complete a la consola Una vez todo dentro SaveRecords completa, la ejecución continuará en MyCallingFunction justo donde estaba cuando SaveChangesAsync() finalizado. ¿Confundido? Aquí hay una salida de ejemplo:

Function Starting
Save Starting
Continuing to execute!
Continuing to execute!
Continuing to execute!
Continuing to execute!
Continuing to execute!
....
Continuing to execute!
Save Complete!
Continuing to execute!
Continuing to execute!
Continuing to execute!
....
Continuing to execute!
Function Complete!

O tal vez:

Function Starting
Save Starting
Continuing to execute!
Continuing to execute!
Save Complete!
Continuing to execute!
Continuing to execute!
Continuing to execute!
....
Continuing to execute!
Function Complete!

Esa es la belleza de async await, su código puede continuar ejecutándose mientras espera que algo termine. En realidad, tendría una función más como esta como su función de llamada:

public async Task MyCallingFunction()

    List myTasks = new List();
    myTasks.Add(SaveRecords(GenerateNewRecords()));
    myTasks.Add(SaveRecords2(GenerateNewRecords2()));
    myTasks.Add(SaveRecords3(GenerateNewRecords3()));
    myTasks.Add(SaveRecords4(GenerateNewRecords4()));

    await Task.WhenAll(myTasks.ToArray());

Aquí tiene cuatro funciones diferentes para guardar registros. al mismo tiempo. MyCallingFunction se completará mucho más rápido usando async await que si el individuo SaveRecords Las funciones se llamaban en serie.

Lo único que no he tocado todavía es el await palabra clave. Lo que esto hace es detener la ejecución de la función actual hasta que lo que sea Task usted está esperando completa. Así que en el caso del original MyCallingFunctionla línea Function Complete no se escribirá en la consola hasta que el SaveRecords termina la función.

Para resumir, si tiene una opción para usar async awaitdebería hacerlo, ya que aumentará en gran medida el rendimiento de su aplicación.

Recuerda que tienes el privilegio reseñar tu experiencia si te fue útil.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *