From acfec75c64cd71e08808db87f633742f36f99f2c Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Wed, 21 Apr 2021 18:19:07 +0300 Subject: [PATCH] Make PooledDbContextFactory public (#24712) Closes #24137 --- ...ityFrameworkServiceCollectionExtensions.cs | 103 +++------- src/EFCore/IDbContextFactory.cs | 4 +- .../Infrastructure/CoreOptionsExtension.cs | 5 + .../Infrastructure/PooledDbContextFactory.cs | 54 ++++++ src/EFCore/Internal/DbContextPool.cs | 13 +- src/EFCore/Internal/PooledDbContextFactory.cs | 35 ---- .../DbContextPoolingTest.cs | 181 ++++++++++-------- 7 files changed, 202 insertions(+), 193 deletions(-) create mode 100644 src/EFCore/Infrastructure/PooledDbContextFactory.cs delete mode 100644 src/EFCore/Internal/PooledDbContextFactory.cs diff --git a/src/EFCore/Extensions/EntityFrameworkServiceCollectionExtensions.cs b/src/EFCore/Extensions/EntityFrameworkServiceCollectionExtensions.cs index 56594389948..691e7ba0949 100644 --- a/src/EFCore/Extensions/EntityFrameworkServiceCollectionExtensions.cs +++ b/src/EFCore/Extensions/EntityFrameworkServiceCollectionExtensions.cs @@ -55,9 +55,7 @@ public static class EntityFrameworkServiceCollectionExtensions /// /// The lifetime with which to register the DbContext service in the container. /// The lifetime with which to register the DbContextOptions service in the container. - /// - /// The same service collection so that multiple calls can be chained. - /// + /// The same service collection so that multiple calls can be chained. public static IServiceCollection AddDbContext( this IServiceCollection serviceCollection, Action? optionsAction = null, @@ -102,9 +100,7 @@ public static IServiceCollection AddDbContext( /// /// The lifetime with which to register the DbContext service in the container. /// The lifetime with which to register the DbContextOptions service in the container. - /// - /// The same service collection so that multiple calls can be chained. - /// + /// The same service collection so that multiple calls can be chained. public static IServiceCollection AddDbContext( this IServiceCollection serviceCollection, Action? optionsAction = null, @@ -149,16 +145,12 @@ public static IServiceCollection AddDbContext /// - /// - /// Sets the maximum number of instances retained by the pool. - /// - /// - /// The same service collection so that multiple calls can be chained. - /// + /// Sets the maximum number of instances retained by the pool. Defaults to 128. + /// The same service collection so that multiple calls can be chained. public static IServiceCollection AddDbContextPool( this IServiceCollection serviceCollection, Action optionsAction, - int poolSize = 128) + int poolSize = DbContextPool.DefaultPoolSize) where TContext : DbContext => AddDbContextPool(serviceCollection, optionsAction, poolSize); @@ -195,16 +187,12 @@ public static IServiceCollection AddDbContextPool( /// will not be called. /// /// - /// - /// Sets the maximum number of instances retained by the pool. - /// - /// - /// The same service collection so that multiple calls can be chained. - /// + /// Sets the maximum number of instances retained by the pool. Defaults to 128. + /// The same service collection so that multiple calls can be chained. public static IServiceCollection AddDbContextPool( this IServiceCollection serviceCollection, Action optionsAction, - int poolSize = 128) + int poolSize = DbContextPool.DefaultPoolSize) where TContextImplementation : DbContext, TContextService where TContextService : class { @@ -253,16 +241,12 @@ public static IServiceCollection AddDbContextPool /// - /// - /// Sets the maximum number of instances retained by the pool. - /// - /// - /// The same service collection so that multiple calls can be chained. - /// + /// Sets the maximum number of instances retained by the pool. Defaults to 128. + /// The same service collection so that multiple calls can be chained. public static IServiceCollection AddDbContextPool( this IServiceCollection serviceCollection, Action optionsAction, - int poolSize = 128) + int poolSize = DbContextPool.DefaultPoolSize) where TContext : DbContext => AddDbContextPool(serviceCollection, optionsAction, poolSize); @@ -308,16 +292,12 @@ public static IServiceCollection AddDbContextPool( /// will not be called. /// /// - /// - /// Sets the maximum number of instances retained by the pool. - /// - /// - /// The same service collection so that multiple calls can be chained. - /// + /// Sets the maximum number of instances retained by the pool. Defaults to 128. + /// The same service collection so that multiple calls can be chained. public static IServiceCollection AddDbContextPool( this IServiceCollection serviceCollection, Action optionsAction, - int poolSize = 128) + int poolSize = DbContextPool.DefaultPoolSize) where TContextImplementation : DbContext, TContextService where TContextService : class { @@ -381,9 +361,7 @@ private static void AddPoolingOptions( /// The to add services to. /// The lifetime with which to register the DbContext service in the container. /// The lifetime with which to register the DbContextOptions service in the container. - /// - /// The same service collection so that multiple calls can be chained. - /// + /// The same service collection so that multiple calls can be chained. public static IServiceCollection AddDbContext( this IServiceCollection serviceCollection, ServiceLifetime contextLifetime, @@ -411,9 +389,7 @@ public static IServiceCollection AddDbContext( /// The to add services to. /// The lifetime with which to register the DbContext service in the container. /// The lifetime with which to register the DbContextOptions service in the container. - /// - /// The same service collection so that multiple calls can be chained. - /// + /// The same service collection so that multiple calls can be chained. public static IServiceCollection AddDbContext( this IServiceCollection serviceCollection, ServiceLifetime contextLifetime, @@ -470,9 +446,7 @@ public static IServiceCollection AddDbContext /// The lifetime with which to register the DbContext service in the container. /// The lifetime with which to register the DbContextOptions service in the container. - /// - /// The same service collection so that multiple calls can be chained. - /// + /// The same service collection so that multiple calls can be chained. public static IServiceCollection AddDbContext( this IServiceCollection serviceCollection, Action? optionsAction, @@ -527,9 +501,7 @@ public static IServiceCollection AddDbContext( /// /// The lifetime with which to register the DbContext service in the container. /// The lifetime with which to register the DbContextOptions service in the container. - /// - /// The same service collection so that multiple calls can be chained. - /// + /// The same service collection so that multiple calls can be chained. public static IServiceCollection AddDbContext( this IServiceCollection serviceCollection, Action? optionsAction, @@ -600,9 +572,7 @@ public static IServiceCollection AddDbContext /// - /// - /// The same service collection so that multiple calls can be chained. - /// + /// The same service collection so that multiple calls can be chained. public static IServiceCollection AddDbContextFactory( this IServiceCollection serviceCollection, Action? optionsAction = null, @@ -659,9 +629,7 @@ public static IServiceCollection AddDbContextFactory( /// The lifetime with which to register the factory and options. /// The default is /// - /// - /// The same service collection so that multiple calls can be chained. - /// + /// The same service collection so that multiple calls can be chained. public static IServiceCollection AddDbContextFactory( this IServiceCollection serviceCollection, Action? optionsAction = null, @@ -727,9 +695,7 @@ public static IServiceCollection AddDbContextFactory( /// The lifetime with which to register the factory and options. /// The default is /// - /// - /// The same service collection so that multiple calls can be chained. - /// + /// The same service collection so that multiple calls can be chained. public static IServiceCollection AddDbContextFactory( this IServiceCollection serviceCollection, Action optionsAction, @@ -794,9 +760,7 @@ public static IServiceCollection AddDbContextFactory( /// The lifetime with which to register the factory and options. /// The default is /// - /// - /// The same service collection so that multiple calls can be chained. - /// + /// The same service collection so that multiple calls can be chained. public static IServiceCollection AddDbContextFactory( this IServiceCollection serviceCollection, Action? optionsAction, @@ -850,16 +814,12 @@ public static IServiceCollection AddDbContextFactory( /// will not be called. /// /// - /// - /// Sets the maximum number of instances retained by the pool. - /// - /// - /// The same service collection so that multiple calls can be chained. - /// + /// Sets the maximum number of instances retained by the pool. Defaults to 128. + /// The same service collection so that multiple calls can be chained. public static IServiceCollection AddPooledDbContextFactory( this IServiceCollection serviceCollection, Action optionsAction, - int poolSize = 128) + int poolSize = DbContextPool.DefaultPoolSize) where TContext : DbContext { Check.NotNull(optionsAction, nameof(optionsAction)); @@ -898,16 +858,12 @@ public static IServiceCollection AddPooledDbContextFactory( /// will not be called. /// /// - /// - /// Sets the maximum number of instances retained by the pool. - /// - /// - /// The same service collection so that multiple calls can be chained. - /// + /// Sets the maximum number of instances retained by the pool. Defaults to 128. + /// The same service collection so that multiple calls can be chained. public static IServiceCollection AddPooledDbContextFactory( this IServiceCollection serviceCollection, Action optionsAction, - int poolSize = 128) + int poolSize = DbContextPool.DefaultPoolSize) where TContext : DbContext { Check.NotNull(serviceCollection, nameof(serviceCollection)); @@ -916,7 +872,8 @@ public static IServiceCollection AddPooledDbContextFactory( AddPoolingOptions(serviceCollection, optionsAction, poolSize); serviceCollection.TryAddSingleton, DbContextPool>(); - serviceCollection.TryAddSingleton, PooledDbContextFactory>(); + serviceCollection.TryAddSingleton>( + sp => new PooledDbContextFactory(sp.GetRequiredService>())); return serviceCollection; } diff --git a/src/EFCore/IDbContextFactory.cs b/src/EFCore/IDbContextFactory.cs index 410e7e387f5..4d45937eb30 100644 --- a/src/EFCore/IDbContextFactory.cs +++ b/src/EFCore/IDbContextFactory.cs @@ -5,8 +5,6 @@ namespace Microsoft.EntityFrameworkCore { /// /// Defines a factory for creating instances. - /// A service of this type is registered in the dependency injection container by the - /// methods. /// /// The type to create. public interface IDbContextFactory @@ -17,7 +15,7 @@ public interface IDbContextFactory /// Creates a new instance. /// /// - /// The caller is responsible for disposing the context; it will not be disposed by the dependency injection container. + /// The caller is responsible for disposing the context; it will not be disposed by any dependency injection container. /// /// /// A new context instance. diff --git a/src/EFCore/Infrastructure/CoreOptionsExtension.cs b/src/EFCore/Infrastructure/CoreOptionsExtension.cs index e51426a7311..d6f4f380d75 100644 --- a/src/EFCore/Infrastructure/CoreOptionsExtension.cs +++ b/src/EFCore/Infrastructure/CoreOptionsExtension.cs @@ -488,6 +488,11 @@ public virtual void ApplyServices(IServiceCollection services) /// The options being validated. public virtual void Validate(IDbContextOptions options) { + if (MaxPoolSize.HasValue && MaxPoolSize <= 0) + { + throw new ArgumentOutOfRangeException(nameof(MaxPoolSize), CoreStrings.InvalidPoolSize); + } + if (_internalServiceProvider != null) { if (ReplacedServices != null) diff --git a/src/EFCore/Infrastructure/PooledDbContextFactory.cs b/src/EFCore/Infrastructure/PooledDbContextFactory.cs new file mode 100644 index 00000000000..eb218e6bd80 --- /dev/null +++ b/src/EFCore/Infrastructure/PooledDbContextFactory.cs @@ -0,0 +1,54 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.EntityFrameworkCore.Internal; + +namespace Microsoft.EntityFrameworkCore.Infrastructure +{ + /// + /// + /// A factory returning pooled instances. Disposing the instance returned by this factory returns + /// them to the internal pooling mechanism. + /// + /// + /// A service of this type is registered in the dependency injection container by the + /// methods. + /// + /// + public class PooledDbContextFactory : IDbContextFactory + where TContext : DbContext + { + private readonly IDbContextPool _pool; + + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + [EntityFrameworkInternal] + public PooledDbContextFactory(IDbContextPool pool) + => _pool = pool; + + /// + /// Initializes a new instance of the class. + /// + /// The options to use for contexts produced by this factory. + /// Sets the maximum number of instances retained by the pool. Defaults to 128. + public PooledDbContextFactory(DbContextOptions options, int poolSize = DbContextPool.DefaultPoolSize) + { + var optionsBuilder = new DbContextOptionsBuilder(options); + + var extension = (options.FindExtension() ?? new CoreOptionsExtension()) + .WithMaxPoolSize(poolSize); + + ((IDbContextOptionsBuilderInfrastructure)optionsBuilder).AddOrUpdateExtension(extension); + + _pool = new DbContextPool(optionsBuilder.Options); + } + + /// + public virtual TContext CreateDbContext() + => (TContext)new DbContextLease(_pool, standalone: true).Context; + } +} diff --git a/src/EFCore/Internal/DbContextPool.cs b/src/EFCore/Internal/DbContextPool.cs index b12e9a214ef..56c5fe89bf4 100644 --- a/src/EFCore/Internal/DbContextPool.cs +++ b/src/EFCore/Internal/DbContextPool.cs @@ -23,7 +23,13 @@ namespace Microsoft.EntityFrameworkCore.Internal public class DbContextPool : IDbContextPool, IDisposable, IAsyncDisposable where TContext : DbContext { - private const int DefaultPoolSize = 32; + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + public const int DefaultPoolSize = 128; private readonly ConcurrentQueue _pool = new(); @@ -42,6 +48,11 @@ public DbContextPool(DbContextOptions options) { _maxSize = options.FindExtension()?.MaxPoolSize ?? DefaultPoolSize; + if (_maxSize <= 0) + { + throw new ArgumentOutOfRangeException(nameof(CoreOptionsExtension.MaxPoolSize), CoreStrings.InvalidPoolSize); + } + options.Freeze(); _activator = CreateActivator(options); diff --git a/src/EFCore/Internal/PooledDbContextFactory.cs b/src/EFCore/Internal/PooledDbContextFactory.cs deleted file mode 100644 index be103bc4291..00000000000 --- a/src/EFCore/Internal/PooledDbContextFactory.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -namespace Microsoft.EntityFrameworkCore.Internal -{ - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public class PooledDbContextFactory : IDbContextFactory - where TContext : DbContext - { - private readonly IDbContextPool _pool; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public PooledDbContextFactory(IDbContextPool pool) - => _pool = pool; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public virtual TContext CreateDbContext() - => (TContext)new DbContextLease(_pool, standalone: true).Context; - } -} diff --git a/test/EFCore.SqlServer.FunctionalTests/DbContextPoolingTest.cs b/test/EFCore.SqlServer.FunctionalTests/DbContextPoolingTest.cs index 5e0005e6b00..870d8fc0695 100644 --- a/test/EFCore.SqlServer.FunctionalTests/DbContextPoolingTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/DbContextPoolingTest.cs @@ -27,85 +27,73 @@ namespace Microsoft.EntityFrameworkCore { public class DbContextPoolingTest : IClassFixture> { + private static DbContextOptionsBuilder ConfigureOptions(DbContextOptionsBuilder optionsBuilder) + where TContext : DbContext + => optionsBuilder + .UseSqlServer(SqlServerNorthwindTestStoreFactory.NorthwindConnectionString) + .EnableServiceProviderCaching(false); + + private static DbContextOptionsBuilder ConfigureOptions(DbContextOptionsBuilder optionsBuilder) + => optionsBuilder + .UseSqlServer(SqlServerNorthwindTestStoreFactory.NorthwindConnectionString) + .EnableServiceProviderCaching(false); + private static IServiceProvider BuildServiceProvider() where TContextService : class where TContext : DbContext, TContextService => new ServiceCollection() - .AddDbContextPool( - ob => - ob.UseSqlServer(SqlServerNorthwindTestStoreFactory.NorthwindConnectionString) - .EnableServiceProviderCaching(false)).AddDbContextPool( - ob => - ob.UseSqlServer(SqlServerNorthwindTestStoreFactory.NorthwindConnectionString) - .EnableServiceProviderCaching(false)).BuildServiceProvider(); + .AddDbContextPool(ob => ConfigureOptions(ob)) + .AddDbContextPool(ob => ConfigureOptions(ob)) + .BuildServiceProvider(); private static IServiceProvider BuildServiceProvider() where TContext : DbContext => new ServiceCollection() - .AddDbContextPool( - ob => - ob.UseSqlServer(SqlServerNorthwindTestStoreFactory.NorthwindConnectionString) - .EnableServiceProviderCaching(false)).AddDbContextPool( - ob => - ob.UseSqlServer(SqlServerNorthwindTestStoreFactory.NorthwindConnectionString) - .EnableServiceProviderCaching(false)).BuildServiceProvider(); + .AddDbContextPool(ob => ConfigureOptions(ob)) + .AddDbContextPool(ob => ConfigureOptions(ob)) + .BuildServiceProvider(); private static IServiceProvider BuildServiceProviderWithFactory() where TContext : DbContext => new ServiceCollection() - .AddPooledDbContextFactory( - ob => - ob.UseSqlServer(SqlServerNorthwindTestStoreFactory.NorthwindConnectionString) - .EnableServiceProviderCaching(false)).AddDbContextPool( - ob => - ob.UseSqlServer(SqlServerNorthwindTestStoreFactory.NorthwindConnectionString) - .EnableServiceProviderCaching(false)).BuildServiceProvider(); + .AddPooledDbContextFactory(ob => ConfigureOptions(ob)) + .AddDbContextPool(ob => ConfigureOptions(ob)) + .BuildServiceProvider(); private static IServiceProvider BuildServiceProvider(int poolSize) where TContextService : class where TContext : DbContext, TContextService => new ServiceCollection() - .AddDbContextPool( - ob => - ob.UseSqlServer(SqlServerNorthwindTestStoreFactory.NorthwindConnectionString) - .EnableServiceProviderCaching(false), - poolSize) - .AddDbContextPool( - ob => - ob.UseSqlServer(SqlServerNorthwindTestStoreFactory.NorthwindConnectionString) - .EnableServiceProviderCaching(false), - poolSize).BuildServiceProvider(); + .AddDbContextPool(ob => ConfigureOptions(ob), poolSize) + .AddDbContextPool(ob => ConfigureOptions(ob), poolSize) + .BuildServiceProvider(); private static IServiceProvider BuildServiceProvider(int poolSize) where TContext : DbContext => new ServiceCollection() - .AddDbContextPool( - ob => - ob.UseSqlServer(SqlServerNorthwindTestStoreFactory.NorthwindConnectionString) - .EnableServiceProviderCaching(false), - poolSize) - .AddDbContextPool( - ob => - ob.UseSqlServer(SqlServerNorthwindTestStoreFactory.NorthwindConnectionString) - .EnableServiceProviderCaching(false), - poolSize) + .AddDbContextPool(ob => ConfigureOptions(ob), poolSize) + .AddDbContextPool(ob => ConfigureOptions(ob), poolSize) .BuildServiceProvider(); private static IServiceProvider BuildServiceProviderWithFactory(int poolSize) where TContext : DbContext => new ServiceCollection() - .AddPooledDbContextFactory( - ob => - ob.UseSqlServer(SqlServerNorthwindTestStoreFactory.NorthwindConnectionString) - .EnableServiceProviderCaching(false), - poolSize) - .AddDbContextPool( - ob => - ob.UseSqlServer(SqlServerNorthwindTestStoreFactory.NorthwindConnectionString) - .EnableServiceProviderCaching(false), - poolSize) + .AddPooledDbContextFactory(ob => ConfigureOptions(ob), poolSize) + .AddDbContextPool(ob => ConfigureOptions(ob), poolSize) .BuildServiceProvider(); + private static IDbContextFactory BuildFactory(bool withDependencyInjection) + where TContext : DbContext + => withDependencyInjection + ? BuildServiceProviderWithFactory().GetService>() + : new PooledDbContextFactory(ConfigureOptions(new DbContextOptionsBuilder()).Options); + + private static IDbContextFactory BuildFactory(bool withDependencyInjection, int poolSize) + where TContext : DbContext + => withDependencyInjection + ? BuildServiceProviderWithFactory(poolSize).GetService>() + : new PooledDbContextFactory(ConfigureOptions(new DbContextOptionsBuilder()).Options, poolSize); + private interface IPooledContext { } @@ -191,12 +179,18 @@ public void Invalid_pool_size() Assert.Throws( () => BuildServiceProvider(poolSize: -1)); + } + [ConditionalTheory] + [InlineData(false)] + [InlineData(true)] + public void Invalid_pool_size_with_factory(bool withDependencyInjection) + { Assert.Throws( - () => BuildServiceProviderWithFactory(poolSize: 0)); + () => BuildFactory(withDependencyInjection, poolSize: 0)); Assert.Throws( - () => BuildServiceProviderWithFactory(poolSize: -1)); + () => BuildFactory(withDependencyInjection, poolSize: -1)); } [ConditionalFact] @@ -242,6 +236,23 @@ public void Validate_pool_size_with_factory() .FindExtension().MaxPoolSize); } + [ConditionalTheory] + [InlineData(false)] + [InlineData(true)] + public void Validate_pool_size_behavior_with_factory(bool withDependencyInjection) + { + var factory = BuildFactory(withDependencyInjection, poolSize: 1); + + var (ctx1, ctx2) = (factory.CreateDbContext(), factory.CreateDbContext()); + ctx1.Dispose(); + ctx2.Dispose(); + + using var ctx3 = factory.CreateDbContext(); + using var ctx4 = factory.CreateDbContext(); + Assert.Same(ctx1, ctx3); + Assert.NotSame(ctx2, ctx4); + } + [ConditionalFact] public void Validate_pool_size_default() { @@ -610,11 +621,13 @@ public async Task Contexts_are_pooled(bool useInterface, bool async) } [ConditionalTheory] - [InlineData(false)] - [InlineData(true)] - public async Task Contexts_are_pooled_with_factory(bool async) + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(true, true)] + public async Task Contexts_are_pooled_with_factory(bool async, bool withDependencyInjection) { - var factory = BuildServiceProviderWithFactory().GetService>(); + var factory = BuildFactory(withDependencyInjection); var context1 = factory.CreateDbContext(); var secondContext1 = factory.CreateDbContext(); @@ -701,11 +714,13 @@ public async Task Context_configuration_is_reset(bool useInterface, bool async) } [ConditionalTheory] - [InlineData(false)] - [InlineData(true)] - public async Task Context_configuration_is_reset_with_factory(bool async) + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(true, true)] + public async Task Context_configuration_is_reset_with_factory(bool async, bool withDependencyInjection) { - var factory = BuildServiceProviderWithFactory().GetService>(); + var factory = BuildFactory(withDependencyInjection); var context1 = factory.CreateDbContext(); @@ -845,12 +860,13 @@ public async Task Default_Context_configuration_is_reset(bool async) } [ConditionalTheory] - [InlineData(false)] - [InlineData(true)] - public async Task Default_Context_configuration_is_reset_with_factory(bool async) + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(true, true)] + public async Task Default_Context_configuration_is_reset_with_factory(bool async, bool withDependencyInjection) { - var factory = BuildServiceProviderWithFactory() - .GetService>(); + var factory = BuildFactory(withDependencyInjection); var context1 = factory.CreateDbContext(); @@ -926,15 +942,16 @@ private static async Task Scoper(Func> getter) => await getter(); [ConditionalTheory] - [InlineData(false)] - [InlineData(true)] - public async Task State_manager_is_reset_with_factory(bool async) + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(true, true)] + public async Task State_manager_is_reset_with_factory(bool async, bool withDependencyInjection) { var weakRef = await Scoper( async () => { - var factory = BuildServiceProviderWithFactory() - .GetService>(); + var factory = BuildFactory(withDependencyInjection); var context1 = factory.CreateDbContext(); @@ -1095,12 +1112,13 @@ public async Task Double_dispose_with_standalone_lease_does_not_enter_pool_twice } [ConditionalTheory] - [InlineData(false)] - [InlineData(true)] - public async Task Can_double_dispose_with_factory(bool async) + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(true, true)] + public async Task Can_double_dispose_with_factory(bool async, bool withDependencyInjection) { - var factory = BuildServiceProviderWithFactory() - .GetService>(); + var factory = BuildFactory(withDependencyInjection); var context = factory.CreateDbContext(); @@ -1167,12 +1185,13 @@ public async Task Provider_services_are_reset(bool useInterface, bool async) } [ConditionalTheory] - [InlineData(false)] - [InlineData(true)] - public async Task Provider_services_are_reset_with_factory(bool async) + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(true, true)] + public async Task Provider_services_are_reset_with_factory(bool async, bool withDependencyInjection) { - var factory = BuildServiceProviderWithFactory() - .GetService>(); + var factory = BuildFactory(withDependencyInjection); var context1 = factory.CreateDbContext();