KSM
KSM

Reputation: 121

How to use constructor to implement DbContext when have different connection string?

Here is my method :

public async task<model> GetMemberList(CancellationToken cancelToken, string connString)
{
   try
   {
       await Task.Run(() =>
       {
           using (var dbContext = DbContext.Create(connString))
           {
              // Code Goes Here....
           }
       }, cancelToken);
   }
   catch
   {
      Throw New Exception(); 
   }
}

In here i used "using" keyword to get dbContext. In every methods I did this because we have different connection string. I hope this is not a bad way to write methods in entity framwork. I realized this when I was going to write unit test for each methods in the business layer. I want to write a constructor to get dbcontext in generic way. I can use Dependency Injection to do that but i don't know how to do that. Can someone give me a way to do it?

Upvotes: 1

Views: 859

Answers (2)

KozhevnikovDmitry
KozhevnikovDmitry

Reputation: 1720

If you just need to hide the logic of building connections string, you can use Factory pattern as it is. In this example building of connection string depends of clientId and is encapsulted in factory. You can mock it as you like in your unit tests for SomeService.

public class CompositionRoot
{
    private readonly IContainer _root;

    public CompositionRoot()
    {
        var builder = new ContainerBuilder();
        builder.RegisterType<SomeService>();
        builder.RegisterType<DbContextFactory>().As<IDbContextFactory>();

        _root = builder.Build();
    }

    public T GetService<T>()
    {
        return _root.Resolve<T>();
    }
}

public interface IDbContextFactory
{
    DbContext Get(int clientId);
}

public class DbContextFactory : IDbContextFactory
{
    public DbContext Get(int clientId)
    {
        // place here any logic you like to build connection string
        var connection = $"Data Source={clientId}db";
        return new DbContext(new SqlConnection(connection), true);
    }
}

public class SomeService
{
    private readonly IDbContextFactory _dbFactory;

    public SomeService(IDbContextFactory dbFactory)
    {
        _dbFactory = dbFactory ?? throw new ArgumentNullException(nameof(dbFactory));
    }

    public async Task<Model> GetMemberList(CancellationToken cancelToken, int clientId)
    {
        using (var dbContext = _dbFactory.Get(clientId))
        {
            // Code Goes Here....

        }

        return null;
    }
}

Upvotes: 0

Akbar Badhusha
Akbar Badhusha

Reputation: 2627

Create and Interface IDbFactory

public interface IDbFactory
{
    DbContext GetConnection();
}

Create a class DbFactory

public class DbFactory : IDbFactory
{ 
    public DbContext GetConnection()
    {
        var connectionString = [get this from web.config]
        return new DbContext.Create(connectionString);
    }
}

Inject dependacny for IDbFactory in the constructor then

public async task<model> GetMemberList(CancellationToken cancelToken)
{
   try
   {
       await Task.Run(() =>
       {
           using (var db = _dbFactory.GetConnection())
           {
              // Code Goes Here....
           }
       }, cancelToken);
   }
   catch
   {
      Throw New Exception(); 
   }
}

Hope it helps

Upvotes: 1

Related Questions