Semplice ma buon esempio su come usare Dapper con Structuremap e l’iniezione delle dipendenze

Sto cercando di capire come usare Dependency Injection con Dapper (IDbConnection) e ancora di poterlo usare incorporato.

Ho trovato un paio di articoli sul web ma non credo che sia facile da capire.

Quello che sto cercando di capire è come rendere testabile questa semplice class:

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(query, new { UserId = userId }).SingleOrDefault(); } } } 

Ho un repository di configurazione simile a questo in modo da poter deridere la richiesta su web.config:

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

Ho letto che è ansible utilizzare ConnectionFactory ma non capisco come implementarlo e so ancora che lo sto eliminando.

Qualcuno può indicarmi la giusta direzione?

Il miglior meccanismo di creazione della connessione, secondo la mia esperienza, è la combinazione di DependencyInjection e ConnectionFactory . Mi sto liberando di IConfigRepository , poiché qui tutto il lavoro viene eseguito utilizzando la fabbrica

I vantaggi sono multipla:

  • Creare un object di connessione in fase di esecuzione nella transazione o nell’ambito del thread
  • Al runtime cambia il fornitore di dati e quindi il database del sistema (usando Connection Factory)

Cosa devi fare (nel codice):

Dichiarare l’object IDBConnection nel livello di accesso ai dati:

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

Dichiarare l’associazione utilizzando un framework DI come Ninject:

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

Creare il DBConnection Factory come segue:

La factory di connessione recupera il provider di connessione e la stringa di connessione dal file di configurazione come segue:

    

L’identificatore è DefaultConnection , che sta utilizzando il provider SqlClient, ma in fase di esecuzione può essere modificato in client diversi come Oracle, MySql

  using System; using System.Data.Common; public static class ConnectionFactory { ///  /// Create DBConnection type based on provider name and connection string ///  ///  ///  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; } } 

Come usarlo:

Per una singola chiamata e disporre

 using(Connection) { ... } 

Per un contesto Transaction, utilizzare così com’è, senza using richiesto

Riguardo a Mocking:

Quale sia il framework Mock che usi per il test delle Unità devi prendere in giro il risultato di UserProfileRepository :: GetUserProfile(string userId) , questo sarebbe più semplice invece di riempire un MockConnection usando la dipendenza Injection, che lo renderà complesso. DI è adatto per l’uso reale, per il riempimento dell’object di connessione in fase di esecuzione