简单但很好的例子,如何使用Dapper与Structuremap和依赖注入

本文关键字:Dapper Structuremap 注入 依赖 何使用 很好 简单 | 更新日期: 2023-09-27 18:15:14

我试图了解如何使用依赖注入与Dapper (IDbConnection),仍然能够使用内置处置。

我在网上找到了几篇文章,但没有一篇我认为是容易理解的。

我想弄清楚的是如何使这个简单的类是可测试的:

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请求。配置:

public class ConfigRepository : IConfigRepository
{
    public string GetConnectionString(string key)
    {
        var conString = ConfigurationManager.ConnectionStrings[key];
        if (conString != null)
        {
            return conString.ConnectionString;
        }
        return string.Empty;
    }
}

我已经读到,你可以使用ConnectionFactory,但还没有弄清楚如何实现它,仍然知道我处置它正确。

谁能给我指个正确的方向?

简单但很好的例子,如何使用Dapper与Structuremap和依赖注入

根据我的经验,最好的连接创建机制是DependencyInjectionConnectionFactory的组合。我正在摆脱IConfigRepository,因为这里所有的工作都是使用工厂完成的

优势多褶皱:

  • 在运行时在事务或线程范围内创建连接对象
  • 在运行时更改系统的数据提供者和数据库(使用连接工厂)

你应当做什么(在代码中):

在数据访问层声明IDBConnection对象:

[Inject] // Property Injection
public IDBConnection Connection {get; set;}

使用像Ninject这样的DI框架声明绑定:

Bind<IDBConnection>().ToMethod(ctx => 
ConnectionFactory.CreateDbConnection("DefaultConnection"));

按如下方式创建DBConnection工厂:

连接工厂从配置文件中获取连接提供者和连接字符串,如下所示:

<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)
{
 ...
}

对于Transaction上下文,按原样使用,不需要using

关于嘲笑:

无论您使用哪个Mock框架进行单元测试,您都必须模拟UserProfileRepository :: GetUserProfile(string userId)的结果,这将比使用依赖注入填充MockConnection更容易,这将使其变得复杂。DI适用于实际用例,用于在运行时填充连接对象