Ejemplo simple pero bueno sobre cómo usar Dapper con Structuremap e inyección de dependencia

c# dapper dependency-injection structuremap

Pregunta

Estoy tratando de entender cómo usar la Inyección de Dependencia con Dapper (IDbConnection) y aún poder usar la eliminación incorporada.

He encontrado un par de artículos en la web, pero no que creo que es fácil de entender.

Lo que estoy tratando de averiguar es cómo hacer que esta clase simple sea comprobable:

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();
        }
    }
}

Tengo un repositorio de configuración que se ve así, así que puedo simular la solicitud a 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;
    }
}

He leído que puede usar ConnectionFactory pero no ha descubierto cómo implementarlo y todavía sé que lo estoy eliminando correctamente.

¿Alguien puede señalarme en la dirección correcta?

Respuesta popular

El mejor mecanismo de creación de conexión según mi experiencia es la combinación de DependencyInjection y ConnectionFactory . Me estoy deshaciendo de IConfigRepository , ya que aquí todo el trabajo se hace usando la fábrica

Las ventajas son múltiples veces

  • Cree un objeto de conexión en tiempo de ejecución en transacción o alcance de subproceso
  • En tiempo de ejecución, cambie el proveedor de datos y, por lo tanto, la base de datos del sistema (utilizando Connection Factory)

Qué debe hacer (en el Código):

Declare el objeto IDBConnection en la capa de acceso a datos:

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

Declare el enlace utilizando un marco DI como Ninject:

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

Cree DBConnection Factory de la siguiente manera:

La fábrica de conexiones obtiene el proveedor de conexión y la cadena de conexión del archivo de configuración de la siguiente manera:

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

El identificador es DefaultConnection , que está utilizando el proveedor SqlClient, pero en tiempo de ejecución se puede cambiar a un cliente diferente como 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;
        }
}

Cómo usarlo:

Para una sola llamada y deseche

using(Connection)
{
 ...
}

Para un contexto de transacción, use tal como está, no se requiere el using

En cuanto a burlarse:

Cualquiera que sea el framework Mock que use para la prueba Unit, tiene que burlarse del resultado de UserProfileRepository :: GetUserProfile(string userId) , esto sería más fácil en lugar de llenar un MockConnection usando Injection, que lo hará complejo. DI es bueno para casos de uso reales, para llenar objetos de conexión en tiempo de ejecución



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué