Unidad de trabajo Entity Framework Core 1.0 con middleware Asp.Net Core o filtro Mvc

Estoy usando EF Core 1.0 (anteriormente conocido como EF7) y ASP.NET Core 1.0 (anteriormente conocido como ASP.NET 5) para una API RESTful.

Me gustaría tener una unidad de trabajo en el ámbito de una solicitud HTTP de tal manera que, al responder a la solicitud HTTP, TODOS los cambios realizados en el DbContext se guardarán en la base de datos o ninguno se guardará (si hubo alguna excepción, por ejemplo).

En el pasado, he usado WebAPI2 para este propósito con NHibernate mediante el uso de un filtro de acción donde comienzo la transacción en la ejecución de la acción, y en la acción ejecutada, finalizo la transacción y cierro la sesión. Esta fue la forma recomendada enhttp://isbn.directory/book/9781484201107

Sin embargo, ahora estoy usando Asp.Net Core (con Asp.Net Core Mvc, aunque esto no debería ser relevante) y Entity Framework que, según tengo entendido, ya implementa una unidad de trabajo.

Creo que tener un middleware conectado a la tubería ASP.NET (antes de MVC) sería la forma correcta de hacer las cosas. Entonces una solicitud sería:

TUBERÍA ASP.NET:MyUnitOfWorkMiddleware ==> MVC Controller ==> Repository ==> MVC Controller ==> MyUnitOfWorkMiddleware

Estaba pensando en hacer que este middleware guardara los cambios de DbContext si no ocurría ninguna excepción, por lo que en mis implementaciones de repositorio ni siquiera necesito hacerdbcontext.SaveChanges() y todo sería como una transacción centralizada. En pseudocódigo, supongo que sería algo como:

class MyUnitOfWorkMiddleware
{
     //..
     1-get an instance of DbContext for this request.
     try {
         2-await the next item in the pipeline.
         3-dbContext.SaveChanges();
     }
     catch (Exception e) {
         2.1-rollback changes (simply by ignoring context)
         2.2-return an http error response
     }
}

¿Esto tiene sentido? ¿Alguien tiene algún ejemplo de algo similar? No puedo encontrar ninguna buena práctica o recomendación sobre esto.

Además, si sigo este enfoque en el nivel de mi controlador MVC, no tendría acceso a ningún ID de recurso creado por la base de datos al PUBLICAR un nuevo recurso porque el ID no se generaría hasta que se guarden los cambios de dbContext (más adelante en la tubería en mi middleware DESPUÉS de que el controlador haya terminado de ejecutarse). ¿Qué sucede si necesito acceder a la ID recién creada de un recurso en mi controlador?

Cualquier consejo sería muy apreciado!

ACTUALIZACIÓN 1: Encontré un problema con mi enfoque para usar middleware para lograr esto porque la instancia de DbContext en el middleware no es la misma que durante la vida útil de MVC (y repositorios). Ver la preguntaEntity Framework Core 1.0 DbContext no tiene ámbito para la solicitud http

ACTUALIZACIÓN 2:Todavía no he encontrado una buena solución. Básicamente, estas son mis opciones hasta ahora:

Guarde los cambios en DB tan pronto como sea posible. Eso significa guardarlo en la implementación del repositorio en sí. El problema con este enfoque es que para una solicitud Http tal vez quiera usar varios repositorios (es decir, guardar algo en la base de datos y luego cargar un blob en un almacenamiento en la nube) y para tener una Unidad de Trabajo tendría que implementar un repositorio que se ocupa de más de una entidad o incluso de más de un método de persistencia (DB y Blob Storage), que anula todo el propósito

Implementar unFiltro de acción donde envuelvo toda la ejecución de la acción en una transacción DB. Al final de la ejecución de la acción del controlador, si no hay excepciones, confirmo los cambios en la base de datos, pero si hay excepciones, revierto y descarto el contexto. El problema con esto es que la acción de mi controlador puede necesitar una ID de entidad generada para devolverla al cliente http (es decir: si recibo un POST / api / cars me gustaría devolver un 201 aceptado con un encabezado de ubicación que identifica el nuevo recurso creado en / api / cars / 123 y el Id 123 aún no estarán disponibles ya que la entidad no se ha guardado en DB y el Id todavía es un 0 temporal). Ejemplo en la acción del controlador para una solicitud de verbo POST:

return CreatedAtRoute("GetCarById", new { carId= carSummaryCreated.Id }, carSummaryCreated); //carSummaryCreated.Id would be 0 until the changes are saved in DB

¿Cómo podría tener toda la acción del controlador, envuelta en una transacción de DB y al mismo tiempo tener disponible cualquier ID generado por la base de datos para devolverlo en la Respuesta Http del controlador? O..¿Hay alguna forma elegante de sobrescribir la respuesta http y establecer el Id en el nivel de filtro de acción una vez que se han confirmado los cambios de la base de datos?

ACTUALIZACIÓN 3: Segúnnathanaldensrcomentario de que podría obtener lo mejor de ambos mundos (envolviendo la ejecución de la acción de mi controlador en una transacción de base de datos _ UoW y también conociendo el Id del nuevo recurso creado incluso antes de que la base de datos confirme cambios) mediante el uso de códigos generados Guids en lugar de confiar en la base de datos para generar el Guid.

Respuestas a la pregunta(3)

Su respuesta a la pregunta