我试图了解如何在Dapper(IDbConnection)中使用依赖注入,并且仍然可以使用内置的dispose。
我在网上发现了一些文章,但我觉得很容易理解。
我想弄清楚的是如何使这个简单的类成为可测试的:
public class UserProfileRepository : IUserProfileRepository
{
private readonly IConfigRepository _configRepository;
public UserProfileRepository(IConfigRepository configRepository)
{
_configRepository = configRepository;
}
public UserProfile GetUserProfile(string userId)
{
const string query = @"Select UserId, UserName
From Users
Where UserId = @UserId";
using (var conn = new SqlConnection(_configRepository.GetConnectionString("MyConnectionString")))
{
conn.Open();
return conn.Query<UserProfile>(query, new { UserId = userId }).SingleOrDefault();
}
}
}
我有一个看起来像这样的配置存储库,所以我可以模拟对web.config的请求:
public class ConfigRepository : IConfigRepository
{
public string GetConnectionString(string key)
{
var conString = ConfigurationManager.ConnectionStrings[key];
if (conString != null)
{
return conString.ConnectionString;
}
return string.Empty;
}
}
我已经读过你可以使用ConnectionFactory但是没有弄清楚如何实现它,但仍然知道我正在处理它。
有人能指出我正确的方向吗?
答案 0 :(得分:4)
根据我的经验,最佳连接创建机制是DependencyInjection
和ConnectionFactory
的组合。我摆脱了IConfigRepository
,因为这里所有的工作都是使用工厂完成的
优势是多重的:
你将做什么(在代码中):
在数据访问层中声明IDBConnection
对象:
[Inject] // Property Injection
public IDBConnection Connection {get; set;}
使用像Ninject这样的DI框架声明绑定:
Bind<IDBConnection>().ToMethod(ctx =>
ConnectionFactory.CreateDbConnection("DefaultConnection"));
按如下方式创建DBConnection Factory:
连接工厂从配置文件中获取连接提供程序和连接字符串,如下所示:
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=<Value>;Initial Catalog=<Value>;User Id=<Value>;Password=<Value>" providerName="System.Data.SqlClient" />
</connectionStrings>
标识符为DefaultConnection
,它使用的是SqlClient提供程序,但在运行时可以更改为不同的客户端,如Oracle, MySql
using System;
using System.Data.Common;
public static class ConnectionFactory
{
/// <summary>
/// Create DBConnection type based on provider name and connection string
/// </summary>
/// <param name="connectionIdentifier"></param>
/// <returns></returns>
public static DbConnection CreateDbConnection(string connectionIdentifier)
{
// Provider name setting
var providerNameValue = ConfigurationManager.ConnectionStrings[connectionIdentifier].ProviderName;
// Connection string setting
var connectionStringValue = ConfigurationManager.ConnectionStrings[connectionIdentifier].ConnectionString;
// Assume failure.
DbConnection connection;
// Null connection string cannot be accepted
if (connectionStringValue == null) return null;
// Create the DbProviderFactory and DbConnection.
try
{
// Fetch provider factory
var factory = DbProviderFactories.GetFactory(providerNameValue);
// Create Connection
connection = factory.CreateConnection();
// Assign connection string
if (connection != null)
connection.ConnectionString = connectionStringValue;
}
catch (Exception ex)
{
connection = null;
}
// Return the connection.
return connection;
}
}
如何使用它:
进行一次通话并处理
using(Connection)
{
...
}
对于交易上下文,按原样使用,不需要using
关于模拟:
您使用哪个Mock框架进行单元测试,您必须模拟UserProfileRepository :: GetUserProfile(string userId)
的结果,这将更容易,而不是使用依赖注入填充MockConnection
,这将使其变得复杂。 DI适用于实际用例,用于在运行时填充连接对象