Unidade de trabalho do Entity Framework Core 1.0 com middleware Asp.Net Core ou filtro Mvc

Estou usando o EF Core 1.0 (anteriormente conhecido ad EF7) e o ASP.NET Core 1.0 (anteriormente conhecido como ASP.NET 5) para uma API RESTful.

Gostaria de ter uma unidade de trabalho com escopo definido para uma solicitação http de tal maneira que, ao responder à solicitação HTTP, TODAS as alterações feitas no DbContext sejam salvas no banco de dados ou nenhuma seja salva (se houver alguma exceção, por exemplo).

No passado, eu usei o WebAPI2 para essa finalidade com o NHibernate, usando um filtro Action, no qual inicio a transação na execução da ação e, na ação executada, encerro a transação e fecho a sessão. Esta foi a maneira recomendada emhttp://isbn.directory/book/9781484201107

No entanto, agora estou usando o Asp.Net Core (com o Asp.Net Core Mvc, embora isso não deva ser relevante) e o Entity Framework que, pelo que entendi, já implementa uma unidade de trabalho.

Eu acho que ter um middleware conectado ao pipeline do ASP.NET (antes do MVC) seria a maneira certa de fazer as coisas. Portanto, uma solicitação seria:

PIPELINE ASP.NET:MyUnitOfWorkMiddleware ==> MVC Controller ==> Repositório ==> MVC Controller ==> MyUnitOfWorkMiddleware

Eu estava pensando em fazer com que esse middleware salvasse as alterações do DbContext se nenhuma exceção acontecesse, para que nas implementações do meu repositório eu nem precise fazerdbcontext.SaveChanges() e tudo seria como uma transação centralizada. No pseudocódigo, acho que seria 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
     }
}

Isso faz sentido? Alguém tem algum exemplo de algo semelhante? Não consigo encontrar nenhuma boa prática ou recomendação sobre isso.

Além disso, se eu seguir essa abordagem no nível do controlador MVC, não teria acesso a nenhum ID de recurso criado pelo banco de dados ao POSTAR um novo recurso, porque o ID não seria gerado até que as alterações do dbContext fossem salvas (posteriormente no pipeline) no meu middleware APÓS o controlador terminar de executar). E se eu precisasse acessar o ID recém-criado de um recurso no meu controlador?

Qualquer conselho seria muito apreciado!

ATUALIZAÇÃO 1: Encontrei um problema com a minha abordagem para usar o middleware para conseguir isso, porque a instância DbContext no middleware não é a mesma que durante a vida útil do MVC (e repositórios). Veja a perguntaEntity Framework Core 1.0 DbContext sem escopo para solicitação http

ATUALIZAÇÃO 2:Ainda não encontrei uma boa solução. Basicamente, estas são minhas opções até agora:

Salve as alterações no banco de dados o mais rápido possível. Isso significa salvá-lo na própria implementação do repositório. O problema com essa abordagem é que, para uma solicitação Http, talvez eu queira usar vários repositórios (por exemplo: salvar algo no banco de dados e depois carregar um blob em um armazenamento em nuvem) e, para ter uma Unidade de Trabalho, eu teria que implementar um repositório que lida com mais de uma entidade ou até mais de um método de persistência (DB and Blob Storage), que derrota todo o propósito

Implementar umFiltro de ação onde envolvo toda a execução da ação em uma transação do banco de dados. No final da execução da ação do controlador, se não houver exceções, confirmo chanches no DB, mas se houver exceções, reverter e descartar o contexto. O problema é que a ação do meu controlador pode precisar de um ID de entidade gerado para devolvê-lo ao cliente http (ou seja: se eu receber um POST / api / cars, gostaria de retornar um 201 Accepted com um cabeçalho de localização que identifique o novo recurso criado em / api / cars / 123 e o ID 123 ainda não estavam disponíveis, pois a entidade não foi salva no banco de dados e o ID ainda é um 0 temporário). Exemplo na ação do controlador para uma solicitação de verbo POST:

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

Como eu poderia ter toda a ação do controlador, envolvida em uma transação de banco de dados e, ao mesmo tempo, ter disponível qualquer ID gerado pelo banco de dados para retorná-lo na resposta Http do controlador? Ou..existe alguma maneira elegante de substituir a resposta http e definir o ID no nível do filtro de ação depois que as alterações no banco de dados forem confirmadas?

ATUALIZAÇÃO 3: ConformenathanaldensrComente o que pude obter o melhor dos dois mundos (envolvendo a execução da ação do meu controlador em uma transação do banco de dados _ UoW e também sabendo o ID do novo recurso criado antes mesmo que o banco de dados cometa alterações) usando Guids gerados por código, em vez de confiar no banco de dados para gere o Guid.

questionAnswers(3)

yourAnswerToTheQuestion