Skip to content

Commit

Permalink
Merge pull request #236 from Brixel/fix-dbcontext-lifecycle
Browse files Browse the repository at this point in the history
fix: Register DbContext as transient instead of using DbContextFactory
  • Loading branch information
BerendWouters authored Oct 12, 2023
2 parents 171754f + 67a9e59 commit a5b121d
Show file tree
Hide file tree
Showing 17 changed files with 86 additions and 101 deletions.
8 changes: 5 additions & 3 deletions Persistence/Extensions/DbContextExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ public static IServiceCollection AddHaSpManContext(
throw new ArgumentException("The value cannot be empty or whitespace.", nameof(connectionString));
}

serviceCollection.AddDbContextFactory<HaSpManContext>(options =>
options.UseSqlServer(connectionString, b => b
serviceCollection.AddDbContext<HaSpManContext>(
options => options.UseSqlServer(connectionString, b => b
.MigrationsAssembly("Persistence")
.MigrationsHistoryTable("__EFMigrationsHistory", "HaSpMan")));
.MigrationsHistoryTable("__EFMigrationsHistory", "HaSpMan")),
ServiceLifetime.Transient);

return serviceCollection;
}

Expand Down
4 changes: 2 additions & 2 deletions Persistence/Repositories/BankAccountRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ public class BankAccountRepository : IBankAccountRepository
{
private readonly HaSpManContext _context;

public BankAccountRepository(IDbContextFactory<HaSpManContext> contextFactory)
public BankAccountRepository(HaSpManContext context)
{
_context = contextFactory.CreateDbContext();
_context = context ?? throw new ArgumentNullException(nameof(context));
}

public void Add(BankAccount account)
Expand Down
4 changes: 2 additions & 2 deletions Persistence/Repositories/FinancialYearRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ public class FinancialYearRepository : IFinancialYearRepository

private readonly HaSpManContext _context;

public FinancialYearRepository(IDbContextFactory<HaSpManContext> contextFactory)
public FinancialYearRepository(HaSpManContext context)
{

_context = contextFactory.CreateDbContext();
_context = context;
}

public Task<FinancialYear?> GetByIdAsync(Guid id, CancellationToken cancellationToken)
Expand Down
4 changes: 2 additions & 2 deletions Persistence/Repositories/MemberRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ public class MemberRepository : IMemberRepository
{
private readonly HaSpManContext _context;

public MemberRepository(IDbContextFactory<HaSpManContext> contextFactory)
public MemberRepository(HaSpManContext context)
{

_context = contextFactory.CreateDbContext();
_context = context;
}
public void Add(Member member)
{
Expand Down
22 changes: 11 additions & 11 deletions Queries/BankAccounts/GetBankAccountById.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using AutoMapper.QueryableExtensions;

using Microsoft.EntityFrameworkCore;

using Persistence;
Expand All @@ -9,19 +11,17 @@ public record GetBankAccountByIdQuery(Guid Id) : IRequest<BankAccountDetail>;
public class GetBankAccountByIdHandler : IRequestHandler<GetBankAccountByIdQuery, BankAccountDetail>
{
private readonly IMapper _mapper;
private readonly IDbContextFactory<HaSpManContext> _contextFactory;
private readonly HaSpManContext _context;

public GetBankAccountByIdHandler(IMapper mapper, IDbContextFactory<HaSpManContext> contextFactory)
public GetBankAccountByIdHandler(IMapper mapper, HaSpManContext context)
{
_mapper = mapper;
_contextFactory = contextFactory;
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
_context = context ?? throw new ArgumentNullException(nameof(context));
}

public async Task<BankAccountDetail> Handle(GetBankAccountByIdQuery request, CancellationToken cancellationToken)
{
var context = await _contextFactory.CreateDbContextAsync(cancellationToken);
var bankAccount = await context.BankAccounts.SingleAsync(b => b.Id == request.Id, cancellationToken: cancellationToken);

return _mapper.Map<BankAccountDetail>(bankAccount);
}
public Task<BankAccountDetail> Handle(GetBankAccountByIdQuery request, CancellationToken cancellationToken)
=> _context.BankAccounts
.Where(b => b.Id == request.Id)
.ProjectTo<BankAccountDetail>(_mapper.ConfigurationProvider)
.SingleAsync(cancellationToken);
}
11 changes: 5 additions & 6 deletions Queries/BankAccounts/SearchBankAccounts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,18 @@ public enum BankAccountDetailOrderOption

public class SearchBankAccountsHandler : IRequestHandler<SearchBankAccountsQuery, Paginated<BankAccountDetailWithTotal>>
{
private readonly IDbContextFactory<HaSpManContext> _contextFactory;
private readonly HaSpManContext _context;
private readonly IMapper _mapper;

public SearchBankAccountsHandler(IDbContextFactory<HaSpManContext> contextFactory, IMapper mapper)
public SearchBankAccountsHandler(HaSpManContext context, IMapper mapper)
{
_contextFactory = contextFactory;
_mapper = mapper;
_context = context ?? throw new ArgumentNullException(nameof(context));
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
}

public async Task<Paginated<BankAccountDetailWithTotal>> Handle(SearchBankAccountsQuery request, CancellationToken cancellationToken)
{
var context = await _contextFactory.CreateDbContextAsync(cancellationToken);
var bankAccountsQueryable = context.BankAccounts
var bankAccountsQueryable = _context.BankAccounts
.AsNoTracking()
.Where(GetFilterCriteria(request.SearchString));

Expand Down
15 changes: 6 additions & 9 deletions Queries/FinancialYears/GetFinancialYearsQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,19 @@ public record GetFinancialYearsQuery() : IRequest<IReadOnlyList<FinancialYear>>;

public class GetFinancialYearsHandler : IRequestHandler<GetFinancialYearsQuery, IReadOnlyList<FinancialYear>>
{
private readonly IDbContextFactory<HaSpManContext> _contextFactory;
private readonly HaSpManContext _context;

public GetFinancialYearsHandler(IDbContextFactory<HaSpManContext> contextFactory)
public GetFinancialYearsHandler(HaSpManContext context)
{
_contextFactory = contextFactory;
_context = context ?? throw new ArgumentNullException(nameof(context));
}

public async Task<IReadOnlyList<FinancialYear>> Handle(GetFinancialYearsQuery request,
CancellationToken cancellationToken)
{
var context = await _contextFactory.CreateDbContextAsync(cancellationToken);
var financialYears = await context.FinancialYears.ToListAsync(cancellationToken);

return financialYears
return await _context.FinancialYears
.OrderByDescending(x => x.StartDate)
.Select(x => new FinancialYear(x.Id, x.StartDate, x.EndDate, x.IsClosed, x.Name))
.ToList();
.ToListAsync(cancellationToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,17 @@ namespace Queries.Members.Handlers.AutocompleteMember;

public class AutocompleteCounterpartyHandler : IRequestHandler<AutocompleteCounterpartyQuery, AutocompleteCounterpartyResponse>
{
private readonly IDbContextFactory<HaSpManContext> _contextFactory;
private readonly HaSpManContext _context;

public AutocompleteCounterpartyHandler(IDbContextFactory<HaSpManContext> contextFactory)
public AutocompleteCounterpartyHandler(HaSpManContext context)
{
_contextFactory = contextFactory;
_context = context ?? throw new ArgumentNullException(nameof(context));
}
public async Task<AutocompleteCounterpartyResponse> Handle(AutocompleteCounterpartyQuery request, CancellationToken cancellationToken)
{
var context = await _contextFactory.CreateDbContextAsync(cancellationToken);

if (request.IsMemberSearch)
{
var members = await context.Members
var members = await _context.Members
.Where(x =>
x.FirstName.ToLower().Contains(request.SearchString.ToLower()) ||
x.LastName.ToLower().Contains(request.SearchString.ToLower()))
Expand All @@ -27,7 +25,7 @@ public async Task<AutocompleteCounterpartyResponse> Handle(AutocompleteCounterpa
return new AutocompleteCounterpartyResponse(members);
}

var counterParties = await context.FinancialYears
var counterParties = await _context.FinancialYears
.SelectMany(x => x.Transactions)
.AsNoTracking()
.Where(x =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,16 @@ namespace Queries.Members.Handlers.GetBankAccountInfos;

public class GetBankAccountInfosHandler : IRequestHandler<GetBankAccountInfos, IReadOnlyList<BankAccountInfo>>
{
private readonly IDbContextFactory<HaSpManContext> _contextFactory;
private readonly HaSpManContext _context;

public GetBankAccountInfosHandler(IDbContextFactory<HaSpManContext> contextFactory)
public GetBankAccountInfosHandler(HaSpManContext context)
{
_contextFactory = contextFactory;
_context = context ?? throw new ArgumentNullException(nameof(context));
}

public async Task<IReadOnlyList<BankAccountInfo>> Handle(GetBankAccountInfos request, CancellationToken cancellationToken)
{
await using var context = _contextFactory.CreateDbContext();
return await context.BankAccounts
=> await _context.BankAccounts
.AsNoTracking()
.Select(x => new BankAccountInfo(x.Id, x.Name))
.ToListAsync(cancellationToken);

}
}
22 changes: 11 additions & 11 deletions Queries/Members/Handlers/GetMemberById/GetMemberByIdHandler.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using AutoMapper.QueryableExtensions;

using Microsoft.EntityFrameworkCore;

using Persistence;
Expand All @@ -9,19 +11,17 @@ namespace Queries.Members.Handlers.GetMemberById;
public class GetMemberByIdHandler : IRequestHandler<GetMemberByIdQuery, MemberDetail>
{
private readonly IMapper _mapper;
private readonly IDbContextFactory<HaSpManContext> _contextFactory;
private readonly HaSpManContext _context;

public GetMemberByIdHandler(IMapper mapper, IDbContextFactory<HaSpManContext> contextFactory)
public GetMemberByIdHandler(IMapper mapper, HaSpManContext context)
{
_mapper = mapper;
_contextFactory = contextFactory;
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
_context = context ?? throw new ArgumentNullException(nameof(context));
}

public async Task<MemberDetail> Handle(GetMemberByIdQuery request, CancellationToken cancellationToken)
{
var context = _contextFactory.CreateDbContext();
var member = await context.Members.SingleAsync(m => m.Id == request.Id, cancellationToken: cancellationToken);

return _mapper.Map<MemberDetail>(member);
}
public Task<MemberDetail> Handle(GetMemberByIdQuery request, CancellationToken cancellationToken)
=> _context.Members
.Where(m => m.Id == request.Id)
.ProjectTo<MemberDetail>(_mapper.ConfigurationProvider)
.SingleAsync(cancellationToken);
}
10 changes: 4 additions & 6 deletions Queries/Members/Handlers/SearchMembers/SearchMembersHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,16 @@ namespace Queries.Members.Handlers.SearchMembers;

public class SearchMembersHandler : IRequestHandler<SearchMembersQuery, Paginated<MemberSummary>>
{
private readonly IDbContextFactory<HaSpManContext> _contextFactory;
private readonly HaSpManContext _context;

public SearchMembersHandler(IDbContextFactory<HaSpManContext> contextFactory)
public SearchMembersHandler(HaSpManContext context)
{
_contextFactory = contextFactory;
_context = context ?? throw new ArgumentNullException(nameof(context));
}

public async Task<Paginated<MemberSummary>> Handle(SearchMembersQuery request, CancellationToken cancellationToken)
{
var context = await _contextFactory.CreateDbContextAsync(cancellationToken);
var memberQueryable = context.Members

var memberQueryable = _context.Members
.AsNoTracking()
.Where(GetTextFilterCriteria(request.SearchString));

Expand Down
10 changes: 4 additions & 6 deletions Queries/Members/MemberExistsByEmailQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,16 @@ public record MemberExistsByEmailQuery(string EmailAddress, Guid? ExcludeId = nu

public class MemberExistsByEmail : IRequestHandler<MemberExistsByEmailQuery, bool>
{
private readonly HaSpManContext _dbContext;
private readonly HaSpManContext _context;

public MemberExistsByEmail(IDbContextFactory<HaSpManContext> dbContextFactory)
public MemberExistsByEmail(HaSpManContext context)
{
_dbContext = dbContextFactory.CreateDbContext();
_context = context ?? throw new ArgumentNullException(nameof(context));
}

public Task<bool> Handle(MemberExistsByEmailQuery request, CancellationToken cancellationToken)
{
return _dbContext.Members
.AsNoTracking()
.AnyAsync(BuildQueryPredicate(request), cancellationToken);
return _context.Members.AnyAsync(BuildQueryPredicate(request), cancellationToken);
}

private static Expression<Func<Member, bool>> BuildQueryPredicate(MemberExistsByEmailQuery request) => request.ExcludeId is null
Expand Down
4 changes: 2 additions & 2 deletions Queries/Members/MemberExistsByNameAndAddressQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ public class MemberExistsByNameAndAddress : IRequestHandler<MemberExistsByNameAn
{
private readonly HaSpManContext _dbContext;

public MemberExistsByNameAndAddress(IDbContextFactory<HaSpManContext> dbContextFactory)
public MemberExistsByNameAndAddress(HaSpManContext dbContext)
{
_dbContext = dbContextFactory.CreateDbContext();
_dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
}

public Task<bool> Handle(MemberExistsByNameAndAddressQuery request, CancellationToken cancellationToken)
Expand Down
11 changes: 5 additions & 6 deletions Queries/Transactions/GetAttachment/GetAttachmentCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,19 @@ public record GetAttachmentQuery(Guid TransactionId, string FileName) : IRequest

public class GetAttachmentHandler : IRequestHandler<GetAttachmentQuery, Attachment>
{
private readonly IDbContextFactory<HaSpManContext> _dbContextFactory;
private readonly HaSpManContext _dbContext;
private readonly IAttachmentStorage _attachmentStorage;

public GetAttachmentHandler(IDbContextFactory<HaSpManContext> dbContextFactory, IAttachmentStorage attachmentStorage)
public GetAttachmentHandler(HaSpManContext dbContext, IAttachmentStorage attachmentStorage)
{
_dbContextFactory = dbContextFactory;
_attachmentStorage = attachmentStorage;
_dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
_attachmentStorage = attachmentStorage ?? throw new ArgumentNullException(nameof(attachmentStorage));
}
public async Task<Attachment> Handle(GetAttachmentQuery request, CancellationToken cancellationToken)
{
var context = await _dbContextFactory.CreateDbContextAsync(cancellationToken);
var transactionId = request.TransactionId;
var transaction =
await context.FinancialYears
await _dbContext.FinancialYears
.SelectMany(x => x.Transactions)
.AsNoTracking()
.SingleOrDefaultAsync(x => x.Id == transactionId, cancellationToken)
Expand Down
25 changes: 12 additions & 13 deletions Queries/Transactions/Handlers/GetTransactionByIdHandler.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Microsoft.EntityFrameworkCore;
using AutoMapper.QueryableExtensions;

using Microsoft.EntityFrameworkCore;

using Persistence;

Expand All @@ -8,21 +10,18 @@ namespace Queries.Transactions.Handlers;

public class GetTransactionByIdHandler : IRequestHandler<GetTransactionByIdQuery, TransactionDetail>
{
private readonly IDbContextFactory<HaSpManContext> _contextFactory;
private readonly HaSpManContext _dbContext;
private readonly IMapper _mapper;

public GetTransactionByIdHandler(IDbContextFactory<HaSpManContext> contextFactory, IMapper mapper)
public GetTransactionByIdHandler(HaSpManContext dbContext, IMapper mapper)
{
_contextFactory = contextFactory;
_mapper = mapper;
_dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
}
public async Task<TransactionDetail> Handle(GetTransactionByIdQuery request, CancellationToken cancellationToken)
{
var context = await _contextFactory.CreateDbContextAsync(cancellationToken);
var transaction = await context.FinancialYears
public Task<TransactionDetail> Handle(GetTransactionByIdQuery request, CancellationToken cancellationToken)
=> _dbContext.FinancialYears
.SelectMany(x => x.Transactions)
.AsNoTracking().SingleAsync(x => x.Id == request.Id, cancellationToken);

return _mapper.Map<TransactionDetail>(transaction);
}
.Where(x => x.Id == request.Id)
.ProjectTo<TransactionDetail>(_mapper.ConfigurationProvider)
.SingleAsync(cancellationToken);
}
12 changes: 5 additions & 7 deletions Queries/Transactions/Handlers/GetTransactionsHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,18 @@ namespace Queries.Transactions.Handlers;

public class GetTransactionsHandler : IRequestHandler<GetTransactionQuery, Paginated<TransactionSummary>>
{
private readonly IDbContextFactory<HaSpManContext> _contextFactory;
private readonly HaSpManContext _dbContext;
private readonly IMapper _mapper;

public GetTransactionsHandler(IDbContextFactory<HaSpManContext> contextFactory, IMapper mapper)
public GetTransactionsHandler(HaSpManContext dbContext, IMapper mapper)
{
_contextFactory = contextFactory;
_mapper = mapper;
_dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext));
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
}

public async Task<Paginated<TransactionSummary>> Handle(GetTransactionQuery request, CancellationToken cancellationToken)
{
var context = await _contextFactory.CreateDbContextAsync(cancellationToken);

var baseQuery = context.FinancialYears
var baseQuery = _dbContext.FinancialYears
.AsNoTracking()
.SelectMany(y => y.Transactions)
.Where(GetFilterCriteria(request.SearchString));
Expand Down
1 change: 1 addition & 0 deletions Web/Pages/Transactions/TransactionForm.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ private async Task TrySetFinancialYearId()
?? throw new Exception($"Couldn't get financial year id for transaction with id {Transaction.Id}");

Transaction.FinancialYearId = financialYear.Id;
await Task.Delay(1000);
}

private async Task SetFinancialYears()
Expand Down

0 comments on commit a5b121d

Please sign in to comment.