Added our own db context pool, that basically bypass the bool until umbraco is in Run mode (#14852)

This commit is contained in:
Bjarke Berg
2023-09-22 10:38:55 +02:00
committed by GitHub
parent 4ee21f19f9
commit d39502674e
2 changed files with 64 additions and 1 deletions

View File

@@ -1,11 +1,13 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.DistributedLocking;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Persistence.EFCore.Factories;
using Umbraco.Cms.Persistence.EFCore.Locking;
using Umbraco.Cms.Persistence.EFCore.Migrations;
using Umbraco.Cms.Persistence.EFCore.Scoping;
namespace Umbraco.Extensions;
@@ -17,6 +19,13 @@ public static class UmbracoEFCoreServiceCollectionExtensions
public static IServiceCollection AddUmbracoEFCoreContext<T>(this IServiceCollection services, DefaultEFCoreOptionsAction? defaultEFCoreOptionsAction = null)
where T : DbContext
{
var optionsBuilder = new DbContextOptionsBuilder<T>();
services.TryAddSingleton<IDbContextFactory<T>>(
sp =>
{
SetupDbContext(defaultEFCoreOptionsAction, sp, optionsBuilder);
return new UmbracoPooledDbContextFactory<T>(sp.GetRequiredService<IRuntimeState>(),optionsBuilder.Options);
});
services.AddPooledDbContextFactory<T>((provider, builder) => SetupDbContext(defaultEFCoreOptionsAction, provider, builder));
services.AddTransient(services => services.GetRequiredService<IDbContextFactory<T>>().CreateDbContext());
@@ -39,6 +48,13 @@ public static class UmbracoEFCoreServiceCollectionExtensions
connectionString = connectionString.Replace(Constants.System.DataDirectoryPlaceholder, dataDirectory);
}
var optionsBuilder = new DbContextOptionsBuilder<T>();
services.TryAddSingleton<IDbContextFactory<T>>(
sp =>
{
SetupDbContext(defaultEFCoreOptionsAction, sp, optionsBuilder);
return new UmbracoPooledDbContextFactory<T>(sp.GetRequiredService<IRuntimeState>(),optionsBuilder.Options);
});
services.AddPooledDbContextFactory<T>(options => defaultEFCoreOptionsAction?.Invoke(options, providerName, connectionString));
services.AddTransient(services => services.GetRequiredService<IDbContextFactory<T>>().CreateDbContext());

View File

@@ -0,0 +1,47 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Cms.Persistence.EFCore.Factories;
/// <inheritdoc/>
internal class UmbracoPooledDbContextFactory<TContext> : PooledDbContextFactory<TContext>
where TContext : DbContext
{
private readonly IRuntimeState _runtimeState;
private readonly DbContextOptions<TContext> _options;
/// <inheritdoc/>
public UmbracoPooledDbContextFactory(IRuntimeState runtimeState, DbContextOptions<TContext> options, int poolSize = 1024 /*DbContextPool<DbContext>.DefaultPoolSize*/) : base(options, poolSize)
{
_runtimeState = runtimeState;
_options = options;
}
/// <inheritdoc/>
public override TContext CreateDbContext()
{
if (_runtimeState.Level == RuntimeLevel.Run)
{
return base.CreateDbContext();
}
else
{
return (TContext?)Activator.CreateInstance(typeof(TContext), _options) ?? throw new InvalidOperationException("Unable to create DbContext");
}
}
/// <inheritdoc/>
public override async Task<TContext> CreateDbContextAsync(CancellationToken cancellationToken = default)
{
if (_runtimeState.Level == RuntimeLevel.Run)
{
return await base.CreateDbContextAsync(cancellationToken);
}
else
{
return (TContext?)Activator.CreateInstance(typeof(TContext), _options) ?? throw new InvalidOperationException("Unable to create DbContext");
}
}
}