fix: Fix unhandled error in OnBeforeSaving db-context

This commit is contained in:
meysamhadeli 2023-01-23 16:32:51 +03:30
parent 17082a2365
commit d54ecc9bb8
10 changed files with 51 additions and 40 deletions

View File

@ -4,7 +4,6 @@ using System.Collections.Immutable;
using BuildingBlocks.Core.Event; using BuildingBlocks.Core.Event;
using BuildingBlocks.Core.Model; using BuildingBlocks.Core.Model;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using System.Data; using System.Data;
using Web; using Web;
using Exception = System.Exception; using Exception = System.Exception;
@ -75,7 +74,7 @@ public abstract class AppDbContextBase : DbContext, IDbContext
foreach (var entry in ChangeTracker.Entries<IAggregate>()) foreach (var entry in ChangeTracker.Entries<IAggregate>())
{ {
var isAuditable = entry.Entity.GetType().IsAssignableTo(typeof(IAggregate)); var isAuditable = entry.Entity.GetType().IsAssignableTo(typeof(IAggregate));
var userId = _currentUserProvider.GetCurrentUserId(); var userId = _currentUserProvider?.GetCurrentUserId() ?? 0;
if (isAuditable) if (isAuditable)
{ {

View File

@ -32,12 +32,12 @@ public static class Extensions
Guard.Against.Null(options, nameof(postgresOptions)); Guard.Against.Null(options, nameof(postgresOptions));
options.UseNpgsql(postgresOptions?.ConnectionString, options.UseNpgsql(postgresOptions?.ConnectionString,
dbOptions => dbOptions =>
{ {
dbOptions.MigrationsAssembly(typeof(TContext).Assembly.GetName().Name); dbOptions.MigrationsAssembly(typeof(TContext).Assembly.GetName().Name);
//ref: https://learn.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency //ref: https://learn.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency
dbOptions.EnableRetryOnFailure(3, TimeSpan.FromSeconds(1), null); dbOptions.EnableRetryOnFailure(3, TimeSpan.FromSeconds(1), null);
}) })
// https://github.com/efcore/EFCore.NamingConventions // https://github.com/efcore/EFCore.NamingConventions
.UseSnakeCaseNamingConvention(); .UseSnakeCaseNamingConvention();
}); });
@ -88,7 +88,8 @@ public static class Extensions
// Replace table names // Replace table names
entity.SetTableName(entity.GetTableName()?.Underscore()); entity.SetTableName(entity.GetTableName()?.Underscore());
var tableObjectIdentifier = StoreObjectIdentifier.Table(entity.GetTableName()?.Underscore()!, entity.GetSchema()); var tableObjectIdentifier =
StoreObjectIdentifier.Table(entity.GetTableName()?.Underscore()!, entity.GetSchema());
// Replace column names // Replace column names
foreach (var property in entity.GetProperties()) foreach (var property in entity.GetProperties())

View File

@ -8,6 +8,7 @@ using Configurations;
using Core.Model; using Core.Model;
using global::Polly; using global::Polly;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Exception = System.Exception;
public class PersistMessageDbContext : DbContext, IPersistMessageDbContext public class PersistMessageDbContext : DbContext, IPersistMessageDbContext
{ {
@ -69,18 +70,25 @@ public class PersistMessageDbContext : DbContext, IPersistMessageDbContext
private void OnBeforeSaving() private void OnBeforeSaving()
{ {
foreach (var entry in ChangeTracker.Entries<IVersion>()) try
{ {
switch (entry.State) foreach (var entry in ChangeTracker.Entries<IVersion>())
{ {
case EntityState.Modified: switch (entry.State)
entry.Entity.Version++; {
break; case EntityState.Modified:
entry.Entity.Version++;
break;
case EntityState.Deleted: case EntityState.Deleted:
entry.Entity.Version++; entry.Entity.Version++;
break; break;
}
} }
} }
catch (Exception ex)
{
throw new Exception("try for find IVersion", ex);
}
} }
} }

View File

@ -11,7 +11,7 @@ namespace Flight.Data
builder.UseNpgsql("Server=localhost;Port=5432;Database=flight;User Id=postgres;Password=postgres;Include Error Detail=true") builder.UseNpgsql("Server=localhost;Port=5432;Database=flight;User Id=postgres;Password=postgres;Include Error Detail=true")
.UseSnakeCaseNamingConvention(); .UseSnakeCaseNamingConvention();
return new FlightDbContext(builder.Options); return new FlightDbContext(builder.Options, null);
} }
} }
} }

View File

@ -10,7 +10,7 @@ using BuildingBlocks.Web;
public sealed class FlightDbContext : AppDbContextBase public sealed class FlightDbContext : AppDbContextBase
{ {
public FlightDbContext(DbContextOptions<FlightDbContext> options, ICurrentUserProvider currentUserProvider = default) : base( public FlightDbContext(DbContextOptions<FlightDbContext> options, ICurrentUserProvider currentUserProvider) : base(
options, currentUserProvider) options, currentUserProvider)
{ {
} }

View File

@ -1,12 +1,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using Flight.Aircrafts.Models;
using Flight.Airports.Models;
using Flight.Data; using Flight.Data;
using Flight.Flights.Enums; using Flight.Flights.Enums;
using Flight.Flights.Models;
using Flight.Seats.Enums; using Flight.Seats.Enums;
using Flight.Seats.Models;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace Unit.Test.Common namespace Unit.Test.Common
@ -18,7 +14,7 @@ namespace Unit.Test.Common
var options = new DbContextOptionsBuilder<FlightDbContext>() var options = new DbContextOptionsBuilder<FlightDbContext>()
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString()).Options; .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString()).Options;
var context = new FlightDbContext(options); var context = new FlightDbContext(options, currentUserProvider: null);
// Seed our data // Seed our data
FlightDataSeeder(context); FlightDataSeeder(context);

View File

@ -16,13 +16,12 @@ using Microsoft.EntityFrameworkCore.Storage;
namespace Identity.Data; namespace Identity.Data;
using System;
public sealed class IdentityContext : IdentityDbContext<User, Role, long, public sealed class IdentityContext : IdentityDbContext<User, Role, long,
UserClaim, UserRole, UserLogin, RoleClaim, UserToken>, IDbContext UserClaim, UserRole, UserLogin, RoleClaim, UserToken>, IDbContext
{ {
private IDbContextTransaction _currentTransaction; public IdentityContext(DbContextOptions<IdentityContext> options) : base(options)
public IdentityContext(DbContextOptions<IdentityContext> options, IHttpContextAccessor httpContextAccessor = default) :
base(options)
{ {
} }
@ -40,7 +39,8 @@ public sealed class IdentityContext : IdentityDbContext<User, Role, long,
var strategy = Database.CreateExecutionStrategy(); var strategy = Database.CreateExecutionStrategy();
return strategy.ExecuteAsync(async () => return strategy.ExecuteAsync(async () =>
{ {
await using var transaction = await Database.BeginTransactionAsync(IsolationLevel.ReadCommitted, cancellationToken); await using var transaction =
await Database.BeginTransactionAsync(IsolationLevel.ReadCommitted, cancellationToken);
try try
{ {
await SaveChangesAsync(cancellationToken); await SaveChangesAsync(cancellationToken);
@ -79,18 +79,25 @@ public sealed class IdentityContext : IdentityDbContext<User, Role, long,
private void OnBeforeSaving() private void OnBeforeSaving()
{ {
foreach (var entry in ChangeTracker.Entries<IVersion>()) try
{ {
switch (entry.State) foreach (var entry in ChangeTracker.Entries<IVersion>())
{ {
case EntityState.Modified: switch (entry.State)
entry.Entity.Version++; {
break; case EntityState.Modified:
entry.Entity.Version++;
break;
case EntityState.Deleted: case EntityState.Deleted:
entry.Entity.Version++; entry.Entity.Version++;
break; break;
}
} }
} }
catch (Exception ex)
{
throw new Exception("try for find IVersion", ex);
}
} }
} }

View File

@ -33,6 +33,7 @@ public static class InfrastructureExtensions
var configuration = builder.Configuration; var configuration = builder.Configuration;
var env = builder.Environment; var env = builder.Environment;
builder.Services.AddScoped<ICurrentUserProvider, CurrentUserProvider>();
builder.Services.AddScoped<IEventMapper, EventMapper>(); builder.Services.AddScoped<IEventMapper, EventMapper>();
builder.Services.AddScoped<IEventDispatcher, EventDispatcher>(); builder.Services.AddScoped<IEventDispatcher, EventDispatcher>();

View File

@ -11,6 +11,6 @@ public class DesignTimeDbContextFactory: IDesignTimeDbContextFactory<PassengerDb
builder.UseNpgsql("Server=localhost;Port=5432;Database=passenger;User Id=postgres;Password=postgres;Include Error Detail=true") builder.UseNpgsql("Server=localhost;Port=5432;Database=passenger;User Id=postgres;Password=postgres;Include Error Detail=true")
.UseSnakeCaseNamingConvention(); .UseSnakeCaseNamingConvention();
return new PassengerDbContext(builder.Options); return new PassengerDbContext(builder.Options, null);
} }
} }

View File

@ -7,8 +7,7 @@ namespace Passenger.Data;
public sealed class PassengerDbContext : AppDbContextBase public sealed class PassengerDbContext : AppDbContextBase
{ {
public PassengerDbContext(DbContextOptions<PassengerDbContext> options, public PassengerDbContext(DbContextOptions<PassengerDbContext> options, ICurrentUserProvider currentUserProvider) :
ICurrentUserProvider currentUserProvider = default) :
base(options, currentUserProvider) base(options, currentUserProvider)
{ {
} }