Reputation: 585
I'm following guidelines in how to setup EF Core to work safely in Blazor & .NET Core 3.1. The MS documentation is here: https://learn.microsoft.com/en-us/aspnet/core/blazor/blazor-server-ef-core?view=aspnetcore-3.1
In the instructions, advice is to create a DbContextFactory which is used to create a dbcontext in each service. All makes sense in the Blazor world, but the code won't compile as AddDbContextFactory does not exist. If there's another way to do it in .Net Core 3.1/ EF Core 3 - I can't see it.
services.AddDbContextFactory<ContactContext>(opt =>
opt.UseSqlite($"Data Source={nameof(ContactContext.ContactsDb)}.db")
.EnableSensitiveDataLogging());
Upvotes: 6
Views: 23011
Reputation: 5481
I found this extension method that the Microsoft docs page is using in its sample github project:
public static IServiceCollection AddDbContextFactory<TContext>(
this IServiceCollection collection,
Action<DbContextOptionsBuilder> optionsAction = null,
ServiceLifetime contextAndOptionsLifetime = ServiceLifetime.Singleton
)
where TContext : DbContext
{
// instantiate with the correctly scoped provider
collection.Add(new ServiceDescriptor(
typeof(IDbContextFactory<TContext>),
sp => new DbContextFactory<TContext>(sp),
contextAndOptionsLifetime
));
// dynamically run the builder on each request
collection.Add(new ServiceDescriptor(
typeof(DbContextOptions<TContext>),
sp => GetOptions<TContext>(optionsAction, sp),
contextAndOptionsLifetime
));
return collection;
}
The all-important interface IDbContextFactory<TContext>
interface is here:
/// <summary>Factory to create new instances of <see cref="DbContext"/>.</summary>
/// <typeparam name="TContext">The type of <seealso cref="DbContext"/> to create.</typeparam>
public interface IDbContextFactory<TContext>
where TContext : DbContext
{
/// <summary>Generate a new <see cref="DbContext"/>.</summary>
/// <returns>A new instance of <see cref="TContext"/>.</returns>
TContext CreateDbContext();
}
And the factory class is here:
public class DbContextFactory<TContext> : IDbContextFactory<TContext>
where TContext : DbContext
{
private readonly IServiceProvider provider;
public DbContextFactory(IServiceProvider provider)
{
this.provider = provider;
}
public TContext CreateDbContext()
{
if (provider == null)
{
throw new InvalidOperationException($"You must configure an instance of IServiceProvider");
}
return ActivatorUtilities.CreateInstance<TContext>(provider);
}
}
GetOptions
method:
private static DbContextOptions<TContext> GetOptions<TContext>(Action<DbContextOptionsBuilder> action, IServiceProvider sp = null)
where TContext: DbContext
{
var optionsBuilder = new DbContextOptionsBuilder < TContext > ();
if (sp != null)
{
optionsBuilder.UseApplicationServiceProvider(sp);
}
action?.Invoke(optionsBuilder);
return optionsBuilder.Options;
}
Upvotes: 11
Reputation: 273274
The page you linked to gives you the code (albeit in pieces) to roll your own.
You will have to add the AddDbContextFactory<TContext>
class and the FactoryExtensions to your project. Download the sample app there to make it complete.
And when you upgrade to net5 just replace it with the library version.
Upvotes: 2
Reputation: 14535
AddDbContextFactory
will be introduced in .NET Core 5. See here: https://devblogs.microsoft.com/dotnet/announcing-entity-framework-core-ef-core-5-0-preview-7/.
Upvotes: 5