Solución para Generics y argumentos dinámicos

c# dapper dynamic service-layer

Pregunta

Intento escribir un contenedor para ocultar gran parte del código que me encuentro repitiendo para cada llamada de DB en Dapper. (es decir, la conexión Sql, try, catch predeterminado y, finalmente) Esencialmente me gustaría hacer algo como el siguiente código, pero entiendo que debido a que hay un parámetro dinámico, no puedo usar genéricos int de esta manera.

De la manera en que me sale el error:

Considere enviar los argumentos dinámicos o llamar al método de extensión sin la sintaxis del método de extensión (haciendo referencia al método conn.Query)

¿Hay alguna manera de refactorizar mi ExecuteQuery o algo así que funcione?

public abtract class IDbAccessService
{
   public LogService Logger { get; set; }

   public virtual IEnumerable<T> ExecuteQuery<T>(string sql, dynamic param, string connString)
      where T : BaseModel
   {
      using (var conn = DataAccessHelpers.GetOpenConnection(connString))
      {
         try
         {
            return conn.Query<T>(sql, param).ToList<T>();
         }
         catch (Exception ex)
         {
            Logger.Logger.Error(ex.Message, ex);
            throw ex;
         }
      }
   }
}

Respuesta aceptada

Los métodos de extensión no se pueden distribuir dinámicamente. Entonces llámelo sin la sintaxis del método de extensión:

static IEnumerable<T> ExecuteQuery<T>(string sql, dynamic param, string connStr)
    where T : BaseModel
{
    using (var conn = DataAccessHelpers.GetOpenConnection(connStr))
    {
        return SqlMapper.Query(conn, sql, param).ToList<T>();
    }
}

También tiene un registro inútil que crea múltiples entradas de registro para un solo error, y la eliminación inútil de la conexión (se realiza automáticamente mediante el uso de bloque).

Sugerencias para el manejo de excepciones:

  • Manejar la excepción y registrarla
  • Ajustar la excepción en la excepción de alto nivel y lanzar esa envoltura (la persona que llama manejará esa excepción de alto nivel, o también la ajustará)
  • No atrape la excepción (quien llama hará la primera o segunda opción)

Respuesta popular

Traté de crear métodos de ayuda como a continuación.

private SqlConnection GetSqlConnection()
        {
            var sqlConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["con1"].ConnectionString);
            sqlConnection.Open();
            return sqlConnection;
        }

public IEnumerable<T> GetAll<T>(string query, object cmdParams = null, CommandType cmdType = CommandType.Text) where T : class
        {
            IEnumerable<T> objList;
            using (var conn = GetSqlConnection())
            {
                objList = conn.Query<T>(query, param: cmdParams, commandTimeout:0, commandType: cmdType);
                conn.Close();
            }
            return objList;
        }

 public IEnumerable<dynamic> Query(string query, object cmdParams = null, CommandType cmdType = CommandType.Text)
        {
            IEnumerable<dynamic> objDyn;
            using (var conn = GetSqlConnection())
            {
                objDyn = conn.Query(query, cmdParams, commandTimeout: 0, commandType: cmdType);
                conn.Close();
            }
            return objDyn;
        }

Desde otra capa:

var param = new DynamicParameters();
param.Add("@name", name);
var objGroupsList = _iDapper.GetAll<CustomerDTO>("dbo.GetCustomersList", param, CommandType.StoredProcedure).ToList();


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow