关于如何将Dapper与Structuremap和依赖项注入结合使用的简单但很好的示例 [英] Simple but good example on how to use Dapper with Structuremap and dependency injection

查看:91
本文介绍了关于如何将Dapper与Structuremap和依赖项注入结合使用的简单但很好的示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图了解如何与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 对象:

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 使用依赖注入,这会使它变得复杂。 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆