D_Inventor
02/18/2025, 11:08 AMIEFCoreScopeProvider
in the controller or do you hide it behind a repository/store? Do you abstract it in some way so you can unit test your business logic without a dependency on the database context class?
I'll share my current approach (which I'm not totally sold on yet) in a responseD_Inventor
02/18/2025, 11:18 AMcsharp
public BookController(BookRequestHandler requestHandler) : ControllerBase
{
public async Task<IActionResult> GetBook(int bookId)
{
var model = await requestHandler.GetBook(bookId);
return model is not null ? Ok(model)
: NotFound();
}
}
request handler:
csharp
public class BookRequestHandler(IBookStore store)
{
public async Task<BookViewModel> GetBook(int id)
{
var dbModel = await store.GetById(id, Projections.BookDetailModel);
return dbModel.ToBookViewModel();
}
}
store
csharp
public class BookStore(IEFCoreScopeProvider<BookStoreContext> scopeProvider)
{
public async Task<T> GetById<T>(int id, Func<IQueryable<BookDTO>, IQueryable<T>> projection)
{
using var scope = scopeProvider.CreateScope();
var result = await scope.ExecuteWithContextAsync(context =>
{
var q = context.Books.Where(e => e.Id == id);
return projection(q).FirstOrDefaultAsync();
});
scope.Complete();
return result;
}
}
Finally, a projection class:
csharp
public static class Projections
{
public static IQueryable<BookDetailProjection> BookDetailModel(IQueryable<BookDTO> query)
=> query.AsNoTracking()
.Select(e => new BookDetailModel(e.Id, e.Title, e.Description));
}
D_Inventor
02/18/2025, 11:19 AMD_Inventor
02/18/2025, 11:19 AMkdx-perbol
02/18/2025, 2:48 PMD_Inventor
02/18/2025, 4:00 PMkdx-perbol
02/18/2025, 10:18 PMIEFCoreScopeProvider
.D_Inventor
02/19/2025, 5:42 AM