Home > Software design >  Blazor dependency injection and EF/DbContext with private NuGet packages
Blazor dependency injection and EF/DbContext with private NuGet packages

Time:10-27

I am trying to set up a Blazor project to be reusable through numerous other projects, and I am having issues understanding how Blazor's DI system works with NuGet packages.

In short, I built a simplistic Blazor app as a ticketing system for bug reports/requests. It collects simple information through input forms (built as components) and uploads tickets to a SQL Server database via Entity Framework and a connection string (stored in AppSettings.JSON). The DbContext is injected into the ticketing app's DI system via AddDbContextFactory. It all works perfectly within the solution.

My goal is: I want to package this ticketing system and reuse it throughout my other apps with minimal setup. In the other apps, I want to reuse the "AddTicket" components, which will simply accept some simple report data and update the ticketing databse.

As a test, I packaged the ticketing app as a NuGet package locally on my machine. I imported it into a separate host app. However, I had to recreate the connection string and the Dependency Injection (with the Context Factory and everything) in the host app to make the package work.

My problem is that I don't understand how Blazor's DI system works when I am building my own NuGet packages and I don't understand the flow of the dependency injections that are in Startup.cs versus what's in the NuGet package.

I just was a simple, reusable form and submittal component, with all of the EF and database logic built into it in the simplest way that I can drop into a dozen external projects.

What is the best way to build a NuGet package so that I don't need to do additional dependency injections in this situation? If I must do an additional entry into the host app's DI system, how do I make it as simple as possible?

CodePudding user response:

When I create a library that has Injection. In my library I create a static class and create and extension method for IServiceCollection

public static class ServiceCollectionExtensions
{
    public static void AddBlazorSyncServer(this IServiceCollection services)
    {
        services.AddScoped<ILogger, Logger<LoggingBroker>>();
        services.AddScoped<ILoggingBroker, LoggingBroker>();
        services.AddScoped<IDateTimeBroker, DateTimeBroker>();
        services.AddTransient<ISyncDatabaseBroker, SyncDatabaseBroker>();
        ...


    }
}

NOTE: In my example SyncDatabaseBroker is a DbContext :

public partial class SyncDatabaseBroker : DbContext, ISyncDatabaseBroker

This makes it a lot easier for the user to setup in their code base. Databases have to be handled a little differently. When I want to manage migrations or share a connection strings I use this approach:

Program.cs (Library consuming server)

...
var migrationsAssembly = typeof(Program).Assembly.FullName;

builder.Services.AddDbContext<ApplicationDbContext>(
    options => options.UseSqlServer(
        connectionString,
        dbOpts => dbOpts.MigrationsAssembly(migrationsAssembly)));


builder.Services.AddDbContext<SyncDatabaseBroker>(
    options => options.UseSqlServer(
        connectionString, 
        dbOpts => dbOpts.MigrationsAssembly(migrationsAssembly)));
...

builder.Services.AddBlazorSyncServer();

Console commands I can then use for the migrations:

Add-Migration InitialApplicationSchema -Context ApplicationDbContext -OutputDir Data/Migrations/Application
Add-Migration InitialSyncSchema -Context SyncDatabaseBroker -OutputDir Data/Migrations/Sync

Update-Database -Context ApplicationDbContext
Update-Database -Context SyncDatabaseBroker 

  • Related