1
votes

How do I connect to multiple database instances from a Blazor WebAssembly project, where I have also added the ASP.NET Core hosted?

My thought was to initiate the DBContexts into the `Startup.cs`` (from Blazor.Server Application which has a reference to Blazor.Client Application):

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<DatabaseContext>(options =>
            options.UseSqlite(
                "connection string holder ..."));
}

like this but I want to let the user choose in my View if they want to do a test run of the App where the SQLite database instance will be created. The regular run will be an instance to SQL Server database. How can I do this in the ConfigureServices method?

Right now I am building the DBContexts classes, are these effected too?

The controllers are not done yet, are ASP.NET Core MVC controllers the right choice?

3
blazor is not MVC, do not mix razor and blazor (docs.microsoft.com/en-us/aspnet/core/blazor/…) - maytham-ɯɐɥʇʎɐɯ
regarding multiple database, it is not thing to do with blazor, check this stackoverflow.com/questions/43767933/… - maytham-ɯɐɥʇʎɐɯ
There is nothing about multiple DB connections in Blazor WASM app.. Blazor WASM is an UI framework just like any frontend framework. For DB operations, you will have to create a Web API and create multiple DbContexts for multiple DB connections. - Rahul
@Rahul Well that was what I have done with the "WebAssembly ASP.NET Core Hosted" meant. My Project structure is now Blazor.Client , Blazor.Server and Blazor.Shared Lib. So now I have the Startup.cs in the Server Project where I will put my Controllers in. Why is the multiple DB connection not possible? I didn't understand that yet. - brstkr
@maytham-ɯɐɥʇʎɐɯ can't I do it in the Blazor.Server Project? Which was created when I checked the ASP.NET Core Hosted option before creating the WebAssembly. - brstkr

3 Answers

2
votes

You can implement that using 2 DB contexts, one interface and a service choosing the context from data sent in API requests:

DB context interface

public interface IDatabaseContext
{
// add all DbSet declaration here
}

db context

public class DatabaseContext : IDatabaseContext
{
// db context implementation
}

Test db context

public class TestDatabaseContext: DatabaseContext
{
// add your constructor
}

DbContext resolver service

public class DbContextResolver
{
    public bool IsTest { get; set; }

Server side DI setup

services.AddDbContext<DatabaseContext>(options =>
            options.UseSqlServer(
                "SqlServer connection string holder ..."))
        .AddDbContext<TestDatabaseContext>(options =>
            options.UseSqlite(
                "Sqlite connection string holder ..."))
        .AddScoped<DbContextResolver>())
        .AddScoped<IDatabaseContext>(p =>
        {
            var resolver = p.GetRequiredService<DbContextResolver>();
            if (resolver.IsTest)
            {
                retrun p.GetRequiredService<TestDatabaseContext>();
            }
            return p.GetRequiredService<DatabaseContext>();
        }));

Select the DB Context from request

public void Configure(IApplicationBuilder app)
{
     app.Use((context, next) =>
     {
          var resolver = context.RequestServices.GetRequiredService<DbContextResolver>();
          resolver.IsTest = context.Request.Query.ContainsKey("test"); // here the context is choosed by query string but you can choose to send an header instead
          return next();
     }
}

use the chosen DB context in controller or a service

public class MyController : Controller
{
     public MyController(IDatabaseContext context)
...
}
0
votes

I haven't tried but you can try something like this-

In Blazor client Program.cs -

builder.Services.AddDatabaseStorage();

In Blazor server Startup.cs -

   public void ConfigureServices(IServiceCollection services)
    {
        services.AddDatabaseStorage();
    }

Create a static class and add all the DB storage interfaces and their implementations-

public static class StorageServiceCollections
{
    public static IServiceCollection AddDatabaseStorage(this IServiceCollection 
 services)
    {
  //you may also return DB service based on certain condition here. Like factory, singleton pattern.
        return services
            .AddSingleton<IDBStorageService, SQLStorageService>()
            .AddSingleton<IMongoDBStorageService, MongoStorageService>();
    }
}

Stablish DB connections and their implementation classes e.g. SQLStorageService, MongoStorageService Something like this -

  public MongoStorageService()
    {
        var client = new MongoClient("mongodb://localhost:23456");
        _mongoDatabase = client.GetDatabase("DB");
    }

Inject in razor components to call them -

@inject IDBStorageService dbStorage
0
votes

Server side Blazor :

services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
services.AddDbContext<ApplicationDbContext>(options => options.UseFirebird(Configuration.GetConnectionString("FirebirdConnection"));

Then register your service:

services.AddSingleton<SalesService>();

where your service has a model you can return using any connection:

public Task<Sales[]> GetSalesRangeAsync(DateTime StartDate, DateTime EndDate)
{
    IDbConnection db = new FbConnection(Startup.FirebirdDatabase);
    
    // QUERY
    return Task.FromResult(Enumerable.Range(0, 1).Select(index => new Sales
    {
        // RESULTS
    }).ToArray());
}