C# 当具有不同的连接字符串时,如何使用构造函数实现DbContext?

C# 当具有不同的连接字符串时,如何使用构造函数实现DbContext?,c#,entity-framework,dependency-injection,C#,Entity Framework,Dependency Injection,以下是我的方法: public async task<model> GetMemberList(CancellationToken cancelToken, string connString) { try { await Task.Run(() => { using (var dbContext = DbContext.Create(connString)) { /

以下是我的方法:

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(); 
   }
}
公共异步任务GetMemberList(CancellationToken cancelToken,string connString) { 尝试 { 等待任务。运行(()=> { 使用(var dbContext=dbContext.Create(connString)) { //代码在这里。。。。 } },取消代币); } 抓住 { 抛出新异常(); } }
在这里,我使用“using”关键字来获取dbContext。在每个方法中,我都这样做,因为我们有不同的连接字符串。我希望这不是一种在实体框架中编写方法的好方法。我在为业务层中的每个方法编写单元测试时意识到了这一点。我想编写一个构造函数以通用方式获取dbcontext。我可以使用依赖注入来实现这一点,但我不知道如何实现。有人能给我一个方法吗

创建和接口IDbFactory

public interface IDbFactory
{
    DbContext GetConnection();
}
创建类DbFactory

public class DbFactory : IDbFactory
{ 
    public DbContext GetConnection()
    {
        var connectionString = [get this from web.config]
        return new DbContext.Create(connectionString);
    }
}
然后在构造函数中为IDbFactory注入dependacny

public async task<model> GetMemberList(CancellationToken cancelToken)
{
   try
   {
       await Task.Run(() =>
       {
           using (var db = _dbFactory.GetConnection())
           {
              // Code Goes Here....
           }
       }, cancelToken);
   }
   catch
   {
      Throw New Exception(); 
   }
}
公共异步任务GetMemberList(CancellationToken cancelToken) { 尝试 { 等待任务。运行(()=> { 使用(var db=\u dbFactory.GetConnection()) { //代码在这里。。。。 } },取消代币); } 抓住 { 抛出新异常(); } }
希望它能帮助您

如果您只需要隐藏构建连接字符串的逻辑,您可以按原样使用Factory模式。在此示例中,连接字符串的构建取决于clientId的类型,并在工厂中封装。您可以在
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;
    }
}
public类CompositionRoot
{
私有只读IContainer\u根目录;
公共合成根()
{
var builder=new ContainerBuilder();
RegisterType();
builder.RegisterType().As();
_root=builder.Build();
}
公共服务
{
返回_root.Resolve();
}
}
公共接口IDbContextFactory
{
DbContext-Get(int-clientId);
}
公共类DbContextFactory:IDbContextFactory
{
public DbContext Get(int clientId)
{
//在这里放置您想要构建连接字符串的任何逻辑
var connection=$“数据源={clientId}db”;
返回新的DbContext(newsqlconnection(connection),true);
}
}
公共类服务
{
私有只读IDBContextFactorydbFactory;
公共服务(IDbContextFactory dbFactory)
{
_dbFactory=dbFactory??抛出新的ArgumentNullException(nameof(dbFactory));
}
公共异步任务GetMemberList(CancellationToken cancelToken,int clientId)
{
使用(var dbContext=_dbFactory.Get(clientId))
{
//代码在这里。。。。
}
返回null;
}
}

您正在使用.Net core吗?否@AkbarBadhusha。您使用什么规则来选择连接字符串?可以将依赖项注入容器配置为将具有不同参数的DbContext作为依赖项注入到不同的类中。例如,SomeService将接收connString连接到“someDb”的dbContext,另一个Service将接收connString连接到“anotherDb”。您可以为不同的连接字符串创建静态变量,并在需要时使用它,如单例模式。否则,如果您不知道连接名称,请创建一个池并从中获取它(如果已经存在),否则请在池中创建新条目我可以问一下您的“wait Task.Run(()=>…)的意图吗?我认为这只是一个不必要的上下文切换,谢谢你的回答。我是这样写方法的,但问题是如何对这种类型的方法进行单元测试。我不能为这个方法编写模拟测试。我被困在这里了。我不能使用静态数据集。我总是要使用数据库。进行单元测试是一种不好的方法。@KSameera,您使用GetMemberList来获得正确的成员列表吗?是否要从GetMemberList发送静态数据集?是此方法用于获取成员列表。对于单元测试(模拟),我想发送不是来自数据库的静态数据集。那么您应该使用模拟类来提供这些细节,对吗?我的意思是,应该有一个接口IMemberDetails,它将被DB类和Mock类继承。然后,您将使用Mock类的实例在测试时发送详细信息。是吗?是的,我想使用Mock类的实例在测试时发送详细信息。这就是为什么我需要改变我的方法。问题是我们只使用一种服务。在配置文件中,我们不能以这种方式使用连接字符串。我们有30个客户。目前,我们有动态连接字符串,对于这些客户端,我们有不同的数据库。根据客户端,我们更改连接字符串。连接字符串具体如何依赖于客户端?客户端有不同的数据库。我们为不同的客户端创建与数据库的连接。