.net nhibernate asynchronous linq-to-nhibernate

.net - ¿Cómo puedo ejecutar consultas de NHibenate de forma asíncrona?



nhibernate asynchronous (5)

Una forma de aumentar la escalabilidad de la aplicación del servidor es ejecutar la operación vinculada a IO (lectura de archivos, sockets, solicitudes web, solicitudes de bases de datos, etc.) de forma asíncrona. Esto no significa que los ejecute en ThreadPool, que solo bloqueará los hilos mientras se ejecuta la operación. La forma correcta es utilizar la API asíncrona (BeginRead, BeginGetResponse, BeginExecuteReader, etc.). El problema está bien descrito en el libro CLR vi C # .

Aquí hay un artículo sobre consultas asíncronas en Linq to SQL .

¿Hay alguna forma de ejecutar la consulta de Nhibernate de forma asíncrona? ¿Qué hay de Linq a NHibernate?

Gracias andrey


A partir de NHibernate v5, async ahora es totalmente compatible!

Aquí hay algunos ejemplos ingeniosos:

Customer customer = await session.GetAsync<Customer>(1); List<Customer> customers = await session.Query<Customer>().ToListAsync(); Customer customer = await session.Query<Customer>() .Where(x => x.Name.Contains("Customer 1")) .SingleOrDefaultAsync();

Actualización de una entidad

using (ISession session = sessionFactory.OpenSession()) using (ITransaction transaction = session.BeginTransaction()) { Customer customer = await session.GetAsync<Customer>(1); customer.Name = "Customer 3"; await session.SaveOrUpdateAsync(customer); await transaction.CommitAsync(); }

Artículo fuente


Aunque todavía no hay soporte para consultas asíncronas en NH, todavía puede superar parcialmente algunos de los efectos no deseados de ejecutar llamadas de db (de larga ejecución) desde el subproceso de solicitud.

Lo que desea es dividir Threadpool entre operaciones de ejecución corta y larga. Por supuesto, esto no es posible con la implementación real de Threadpool y TPL, pero puede ayudarse a sí mismo con bastante facilidad escribiendo su propia cola de Productor / Consumidor con elementos que se pueden esperar y con una concurencia personalizada.

Por favor, eche un vistazo al ejemplo que he reunido: https://gist.github.com/3746240

El código está copiado / pegado del gran libro "C # 5.0 en una cáscara de nuez: la referencia definitiva" por Joseph Albahari y Ben Albahari con modificaciones hechas por mí, lo que hizo que el programador creara hilos de trabajo dedicados para los procesos.


Lamentablemente no. NHibernate no expone la implementación interna de la ejecución del comando de la manera en que lo hace L2S.

Tendrá que usar el conjunto de subprocesos O crear un parche para NH para agregar soporte de consultas asíncronas. Eso sería muy bienvenido por la comunidad y sería un buen ejercicio (pero no es en absoluto trivial)


Las llamadas asíncronas múltiples se pueden reescribir con futuros

var footask = QueryFooAsync(); var bartask = QueryBarAsync(); var baztask = QueryBazAsync(); var foos = await footask; var bars = await bartask; var baz = await baztask; // do something with foos, bars, baz

puede ser reemplazado con

var foos = session.Query<Foo>().....ToFuture(); var bars = session.Query<Bar>().....ToFuture(); var baz = session.Query<Bazes>().....ToFutureValue(); await Task.Factory.StartNew(() => var ignored = baz.Value) // await the results // do something with foos, bars, baz

Esto incluso tiene el beneficio sobre el código asíncrono de que el tiempo de ida y vuelta solo se paga una vez en lugar de 3 veces.


Tenga en cuenta que las llamadas de base de datos asíncronas NO implican una mejor escalabilidad general por sí mismas. Recomiendo leer el artículo " ¿Deben las llamadas de mi base de datos ser asíncronas? " Para un análisis en profundidad. Aquí hay una cita de ese artículo:

Un respetado arquitecto de DB / Web llegó a decir:
Para las aplicaciones de base de datos que utilizan operaciones asíncronas para reducir el número de subprocesos bloqueados en el servidor web es casi siempre una pérdida total de tiempo. Un pequeño servidor web puede manejar fácilmente más solicitudes de bloqueo simultáneas que las que el back-end de su base de datos puede procesar simultáneamente. En su lugar, asegúrese de que sus llamadas de servicio sean baratas en la base de datos y limite la cantidad de solicitudes que se ejecutan simultáneamente a un número que haya probado que funcione correctamente y maximice el rendimiento general de la transacción.