UseInternalServiceProvider
FoxTes opened this issue · 9 comments
Using UseInternalServiceProvider()
I get incorrect behavior of this library. It just stops working.
UseInternalServiceProvider()
is required for the factory when creating the migration. Can you tell me how you can work around this problem?
I have already seen PR on this topic before, but there is no solution there.
public class ApplicationContextFactory : IDesignTimeDbContextFactory<ApplicationContext>, IAsyncDisposable
{
private readonly NpgsqlDataSource _dataSource;
private readonly IServiceProvider _serviceProvider;
public ApplicationContextFactory()
{
var builder = WebApplication.CreateBuilder(Array.Empty<string>());
var connectionString = builder.Configuration.GetConnectionString(nameof(ApplicationContext));
builder.Services
.AddEntityFrameworkNpgsql()
.AddEntityFrameworkNamingConventions();
var dataSourceBuilder = new NpgsqlDataSourceBuilder(connectionString);
_dataSource = dataSourceBuilder.Build();
_serviceProvider = builder.Build().Services;
}
public ApplicationContext CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder<ApplicationContext>();
optionsBuilder
.UseNpgsql(_dataSource)
.UseSnakeCaseNamingConvention()
.UseInternalServiceProvider(_serviceProvider);
return new ApplicationContext(optionsBuilder.Options);
}
public ValueTask DisposeAsync()=> _dataSource.DisposeAsync();
}
@FoxTes you should in almost all cases not be using UseInternalServiceProvider in a normal app - any particular reason you're doing that?
@roji
I use UseInternalServiceProvider()
only in IDesignTimeDbContextFactory
.
I need to get in the context of IOptions
(and maybe other servicies) for the OnModelCreating()
method.
In the application itself, DI solves this problem.
Is it possible to solve the problem with migrations and IDesignTimeDbContextFactory
?
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new WorkoutTypeEntityTypeConfiguration(
this.GetService<IClockService>(),
this.GetService<IOptions<TenantOption>>()));
}
public class WorkoutTypeEntityTypeConfiguration(
IClockService clockService,
IOptions<TenantOption> option)
: IEntityTypeConfiguration<WorkoutTypeEntity>
{
public void Configure(EntityTypeBuilder<WorkoutTypeEntity> builder)
{
builder
.HasQueryFilter(e => e.TenantId == option.Value.Id);
builder
.HasData(FastEnum
.GetValues<WorkoutType>()
.Select(type => new WorkoutTypeEntity
{
Id = type,
Description = type.GetEnumMemberValue()!,
CreatedDateTime = clockService.LocalNow,
TenantId = option.Value.Id
}));
}
}
Well, I solved the problem not in the most obvious way :)
public class ApplicationContextFactory : IDesignTimeDbContextFactory<ApplicationContext>
{
private readonly IServiceProvider _serviceProvider;
public ApplicationContextFactory()
{
var builder = WebApplication.CreateBuilder(Array.Empty<string>())
.AddOptions()
.AddDbContextFactoryServices();
var dataSourceBuilder = new NpgsqlDataSourceBuilder(
builder.Configuration.GetConnectionString(nameof(ApplicationContext)));
dataSourceBuilder.MapEnum<ActionType>();
dataSourceBuilder.MapEnum<WorkoutType>();
builder.Services.AddDbContext<ApplicationContext>(
options => options
.UseNpgsql(dataSourceBuilder.Build(), option => option.UseNodaTime())
.UseSnakeCaseNamingConvention(),
ServiceLifetime.Singleton);
_serviceProvider = builder.Build().Services;
}
public ApplicationContext CreateDbContext(string[] args) =>
_serviceProvider.GetRequiredService<ApplicationContext>();
}
@FoxTes great that you could get rid of UseInternalServiceProvider(). If you're simply looking for the design-time context to be the same thing that your application sets up in WebApplication, you maybe don't need to define a IDesignTimeDbContextFactory at all - see the docs.
In any case, I'll go ahead and close this as the problem seems to be solved.
ASP.NET Core Web Host or .NET Core Generic Host
In my case, WebApplication
is used and therefore this is not suitable for me
@FoxTes the docs are probably out of date, and WebApplication should work as well; have you tried and seen it not working?
Yeap, it's worked! Thanks for the hint
Great!