Code: Select all
PM> Add-Migration InitialSpecMakerDb -OutputDir Data
Code: Select all
Build started...
Build succeeded.
Code: Select all
ApplicationDbContext
Hauptcode:
appsettings.json:
Code: Select all
"ConnectionStrings": {
"DefaultConnection": "Data Source=.;Initial Catalog=SmartSpecMakers;Integrated Security=True;TrustServerCertificate=True"
},
Code: Select all
public class ApplicationDbContext : IdentityDbContext, IApplicationDbContext
{
private readonly ICurrentUserService _currentUserService;
private readonly IDateTimeService _dateTimeService;
private readonly IMediator _mediator;
public ApplicationDbContext(DbContextOptions options, IDateTimeService dateTimeService, ICurrentUserService currentUserService, IMediator mediator) : base(options)
{
ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
_dateTimeService = dateTimeService;
_currentUserService = currentUserService;
_mediator = mediator;
}
public DbSet RefreshTokens { get; set; }
public DbSet ApplicationUsers { get; set; }
public DbSet ApplicationRoles { get; set; }
// Override OnModelCreating to apply the entity configurations
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Call the base implementation for IdentityDbContext
base.OnModelCreating(modelBuilder);
// Apply entity configurations using Fluent API
// Additional Identity-related configurations
modelBuilder.ApplyConfiguration(new ApplicationUserConfigurations());
...
}
public override async Task SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
{
foreach (var entry in ChangeTracker.Entries())
{
switch (entry.State)
{
case EntityState.Added:
entry.Entity.CreatedBy = _currentUserService.UserName ?? string.Empty;
entry.Entity.CreatedAtUtc = _dateTimeService.NowUtc;
break;
case EntityState.Modified:
entry.Entity.LastModifiedBy = _currentUserService.UserName ?? string.Empty;
entry.Entity.LastModifiedAtUtc = _dateTimeService.NowUtc;
break;
case EntityState.Deleted:
entry.State = EntityState.Modified;
entry.Entity.IsDeleted = true;
entry.Entity.DeletedBy = _currentUserService.UserName ?? string.Empty;
entry.Entity.DeletedAtUtc = _dateTimeService.NowUtc;
break;
}
}
return await base.SaveChangesAsync(cancellationToken);
}
public new DbSet Set() where T : class
{
return base.Set();
}
public new EntityEntry Entry(T entity) where T : class
{
return base.Entry(entity);
}
public new async Task AddAsync(T entity, CancellationToken cancellationToken = default) where T : class
{
return await base.AddAsync(entity, cancellationToken);
}
public new void Update(T entity) where T : class
{
base.Update(entity);
}
public new void Remove(T entity) where T : class
{
base.Remove(entity);
}
}
Code: Select all
public static class PersistenceServiceRegistration
{
public static IServiceCollection ConfigurePersistenceServices(this IServiceCollection services, IConfiguration configuration)
{
services.AddScoped();
services.AddScoped(provider => provider.GetService());
// OAuth and Identity services
services.AddTransient();
services.AddScoped();
// Register repositories
RegisterRepositories(services);
// Configure JWT Authentication
ConfigureJwtAuthentication(services, configuration);
// Configure DbContext
ConfigureDbContext(services, configuration);
// Configure Identity
ConfigureIdentity(services, configuration);
// Database initialization and seeding
ConfigureDatabaseInit(services);
// Register Permission and Role services
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddHttpContextAccessor();
// Configure CORS
services.AddCors(options =>
{
options.AddPolicy("AllowAll", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
return services;
}
private static void ConfigureDatabaseInit(IServiceCollection services)
{
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.Scan(scan => scan
.FromAssembliesOf(typeof(ICustomSeeder))
.AddClasses(classes => classes.AssignableTo())
.AsImplementedInterfaces()
.WithTransientLifetime());
// Register individual seeders
services.AddTransient();
}
private static void ConfigureJwtAuthentication(IServiceCollection services, IConfiguration configuration)
{
var jwtSettings = configuration.GetSection(nameof(JWTSettings)).Get();
services.AddSingleton(jwtSettings);
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtSettings.Secret)),
ValidateIssuer = true,
ValidIssuer = jwtSettings.Issuer,
ValidateAudience = true,
ValidAudience = jwtSettings.Audience,
RequireExpirationTime = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
services.AddSingleton(tokenValidationParameters);
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = tokenValidationParameters;
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
if (context.Exception is SecurityTokenExpiredException)
{
// context.Response.Headers.Add("Token-Expired", "true");
context.Response.Headers["Token-Expired"] = "true";
//context.Response.Headers.Append("Token-Expired", "true");
}
return Task.CompletedTask;
}
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("RequireAdminRole", policy =>
policy.RequireRole(Roles.DatabaseAdmin, Roles.SuperAdmin));
});
}
private static void ConfigureDbContext(IServiceCollection services, IConfiguration configuration)
{
if (configuration.GetValue("UseInMemoryDatabase"))
{
services.AddDbContext(options =>
options.UseInMemoryDatabase("ApplicationDb"));
}
else
{
services.AddDbContext(options =>
{
options.UseSqlServer(
configuration.GetConnectionString("DefaultConnection"),
sqlOptions =>
{
sqlOptions.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName);
sqlOptions.EnableRetryOnFailure(
maxRetryCount: 5,
maxRetryDelay: TimeSpan.FromSeconds(30),
errorNumbersToAdd: null);
});
options.EnableSensitiveDataLogging(configuration.GetValue("EnableSensitiveDataLogging"));
});
}
}
private static void ConfigureIdentity(IServiceCollection services, IConfiguration configuration)
{
var identityOptions = configuration.GetSection(nameof(IdentityOptions)).Get();
services.AddIdentity(options =>
{
// Password settings
options.Password.RequiredLength = identityOptions.RequiredLength;
options.Password.RequireDigit = identityOptions.RequiredDigit;
options.Password.RequireLowercase = identityOptions.RequireLowercase;
options.Password.RequireUppercase = identityOptions.RequireUppercase;
options.Password.RequiredUniqueChars = identityOptions.RequiredUniqueChars;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromDays(identityOptions.LockoutTimeSpanInDays);
options.Lockout.MaxFailedAccessAttempts = identityOptions.MaxFailedAttempts;
options.Lockout.AllowedForNewUsers = true;
// User settings
options.User.RequireUniqueEmail = true;
options.SignIn.RequireConfirmedEmail = false;
})
.AddEntityFrameworkStores()
.AddDefaultTokenProviders();
}
private static void RegisterRepositories(IServiceCollection services)
{
// Generic repository registration
services.AddScoped(typeof(IGenericRepositoryAsync), typeof(GenericRepositoryAsync));
// Identity repositories
services.AddScoped();
services.AddScoped();
// Specific service registrations
services.AddScoped();
}
}