关于如何将Dapper与Structuremap和依赖项注入结合使用的简单但很好的示例 [英] Simple but good example on how to use Dapper with Structuremap and dependency injection
问题描述
我试图了解如何与Dapper(IDbConnection)一起使用依赖注入,并且仍然能够使用内置的Dispose。
I am trying to understand how to use Dependency Injection with Dapper (IDbConnection) and still being able to use built in dispose.
我发现了几篇文章
我要弄清楚的是如何使这个简单的类可测试:
What I am trying to figure out is how to make this simple class be testable:
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的请求:
I have a config repository that looks like this so I can mock the request to web.config away:
public class ConfigRepository : IConfigRepository
{
public string GetConnectionString(string key)
{
var conString = ConfigurationManager.ConnectionStrings[key];
if (conString != null)
{
return conString.ConnectionString;
}
return string.Empty;
}
}
我读到您可以使用ConnectionFactory,但尚未使用弄清楚如何实现它,并且仍然知道我正确地配置了它。
I have read that you could use ConnectionFactory but has not figur out how to implement it and still know I am disposing it correct.
有人可以指出我正确的方向吗?
Can anyone point me in the right direction?
推荐答案
根据我的经验,最好的连接创建机制是 DependencyInjection
和 ConnectionFactory 的组合code>。我摆脱了
IConfigRepository
,因为这里所有工作都是使用工厂完成的
Best connection creation mechanism as per my experience is the combination of DependencyInjection
and ConnectionFactory
. I am getting rid of IConfigRepository
, since here all the work is done using factory
优点是多方面的:
Advantages are Multi fold:
- 在运行时在事务或线程范围内创建连接对象
- 在运行时更改数据提供者,并因此更改系统的数据库(使用Connection Factory)
您应执行的操作(用代码表示):
What you shall do (in Code):
声明 IDBConnection $数据访问层中的c $ c>对象:
Declare the IDBConnection
object in the Data access Layer:
[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
Identifier is DefaultConnection
, which is using the SqlClient provider, but at run time can be changed to the different client like 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;
}
}
使用方法:
How to use it:
用于单个呼叫并处理
using(Connection)
{
...
}
对于事务上下文,请按原样使用,无需使用
For a Transaction context, use as-is, no using
required
关于模拟:
Regarding Mocking:
您用于单元测试的哪个Mock框架您必须模拟 UserProfileRepository :: GetUserProfile(string userId)
的结果,这比填充 MockConnection $ c $更容易c>使用依赖注入,这会使它变得复杂。 DI非常适合实际用例,可以在运行时填充连接对象
Which ever Mock framework you use for the Unit testing you have to mock the result of the UserProfileRepository :: GetUserProfile(string userId)
, this would be easier instead of filling a MockConnection
using dependency Injection, which will make it complex. DI is good for real use case, for filling connection object at runtime
这篇关于关于如何将Dapper与Structuremap和依赖项注入结合使用的简单但很好的示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!