Dynamic Web Api Connection String

I view my repository operations via web api. The repository was implemented using the Entity and Pattern of Work infrastructure. I have many instances of the same database. Each of them represents the data of another Client. Now the problem is, how can I dynamically set the connection string through every webapi call? Should I get a connection string parameter with every call? Or should I host web api on the client?

+4
source share
2 answers

Based on the information provided, I would use the same controller and look at the connection string, rather than placing separate instances of the web API for each client. It would be more difficult to place multiple instances, and, given the only difference indicated in the connection string, I do not think the complexity will be justified.

The first thing we need to do is determine which client is being called in order to get the corresponding connection string. This can be done using tokens, headers, request data, or routing. Routing is the easiest and most affordable for clients, so I will demonstrate its use; however, carefully review your requirements when deciding how you will make the decision.

[Route( "{clientId}" )]
public Foo Get( string clientId ) { /* ... */ }

DbContext . DI, , , , , . factory, . Func<string, IUnitOfWork> , "clientId" IUnitOfWork. .

[RoutePrefix("foo")]
public class FooController : ApiController
{  
    private Func<string, IUnitOfWork> unitOfWorkFactory;

    public FooController( Func<string, IUnitOfWork> unitOfWorkFactory )
    {
        this.unitOfWorkFactory = unitOfWorkFactory;
    }

    [Route( "{clientId}" )]
    public Foo Get( string clientId )
    {
        var unitOfWork = unitOfWorkFactory(clientId);
        // ...
    }
}

, , , Func<string, IUnitOfWork>. . Autofac.

protected override void Load( ContainerBuilder builder )
{
    // It is expected `MyDbContext` has a constructor that takes the connection string as a parameter
    // This registration may need to be tweaked depending on what other constructors you have.
    builder.Register<MyDbContext>().ForType<DbContext>().InstancePerRequest();

    // It is expected `UnitOfWork` constructor takes a `DbContext` as a parameter
    builder.RegisterType<UnitOfWork>().ForType<IUnitOfWork>().InstancePerRequest();

    builder.Register<Func<string, Bar>>(
        c =>
            {
                var dbContextFactory = c.Resolve<Func<string, DbContext>>();
                var unitOfWorkFactory = c.Resolve<Func<DbContext, IUnitOfWork>>();

                return clientId =>
                    {
                        // You may have injected another type to help with this
                        var connectionString = GetConnectionStringForClient(clientId);
                        return unitOfWorkFactory(dbContextFactory(connectionString));
                    };
            });
 }

Autofac , , Autofac , .

, .


:

builder.Register<Func<string, IEmployeeService>>(
    c =>
        {
            var dbContextFactory = c.Resolve<Func<string, IMainContext>>();
            var unitOfWorkFactory = c.Resolve<Func<IMainContext, IUnitOfWork>>();
            var repositoryFactory = c.Resolve<Func<IMainContext, IEmployeeRepository>>();
            var serviceFactory = c.Resolve<Func<IUnitOfWork, IEmployeeService>>();

            return clientId =>
                {
                    // You may have injected another type to help with this
                    var connectionString = GetConnectionStringForClient(clientId);

                    IMainContext dbContext = dbContextFactory(connectionString);
                    IUnitOfWork unitOfWork = unitOfWorkFactory(dbContext);
                    IEmployeeRepository employeeRepository = repositoryFactory(dbContext);
                    unitOfWork.employeeRepositoty = employeeRepository;

                    return serviceFactory(unitOfWork);
                };
        });

, - , , , ( ) , , .

+4

DbContext

:

public class AwesomeContext : DbContext
{
    public AwesomeContext (string connectionString)
        : base(connectionString)
    {
    }
    public DbSet<AwesomePeople> AwesomePeoples { get; set; }
}

DbContext :

   using(AwesomeContext context = new AwesomeContext("newConnectionString"))
   {
     return context.AwesomePeoples.ToList();
   }

, ConnectionStrings , DB /const (, ).

/ ,

DbContext:

    public void SetConnectionString(string connectionString)
    {
        this.Database.Connection.ConnectionString = connectionString;
    }

:

   using(AwesomeContext context = new AwesomeContext())
   {

    context.SetConnectionString(ConfigurationManager.ConnectionStrings["newConnectionString"].ConnectionString)
    return context.AwesomePeoples.ToList();

   }
0

Source: https://habr.com/ru/post/1589497/


All Articles