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个客户。目前,我们有动态连接字符串,对于这些客户端,我们有不同的数据库。根据客户端,我们更改连接字符串。连接字符串具体如何依赖于客户端?客户端有不同的数据库。我们为不同的客户端创建与数据库的连接。