Simple but good example on how to use Dapper with Structuremap and dependency injection

吃可爱长大的小学妹 提交于 2019-12-03 15:00:35

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:

  • Create a connection object at runtime in transaction or thread scope
  • At runtime change the data provider and thus database of the system ( using Connection Factory)

What you shall do (in Code):

Declare the IDBConnection object in the Data access Layer:

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

Declare the binding using a DI framework like Ninject:

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

Create the DBConnection Factory as follows:

Connection factory fetches the Connection provider and connection string from the config file as follows:

<connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=<Value>;Initial Catalog=<Value>;User Id=<Value>;Password=<Value>" providerName="System.Data.SqlClient" />
</connectionStrings>

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:

For a single call and dispose

using(Connection)
{
 ...
}

For a Transaction context, use as-is, no using required

Regarding Mocking:

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!