Restablecer caché para Dapper

asp.net-mvc c# dapper

Pregunta

¿Hay alguna manera de restablecer el caché que genera Dapper ? Bajé una columna de la tabla en mi base de datos, y recibí el error "columna no encontrada". Restablecé IIS y funcionó bien después de eso.

¿Se puede restablecer sin reiniciar IIS? Gracias.

Respuesta popular

Actualización 2018-02-08

El código Dapper ha cambiado bastante desde que se escribió esta respuesta hace casi 5 años. Como Marc Gravell comentó sobre la pregunta, esto no debería haber sido necesario cuando se formuló la pregunta, por lo que probablemente tampoco sea de mucha utilidad hoy.

El código puede o no funcionar más. Incluso si todavía funciona, no es óptimo, así que no podría recomendarlo de buena fe. Úselo bajo su propio riesgo.


La línea 227 de Database.cs muestra:

static ConcurrentDictionary<Type, string> tableNameMap = new ConcurrentDictionary<Type, string>();
static ConcurrentDictionary<Type, List<string>> paramNameCache = new ConcurrentDictionary<Type, List<string>>();

lo que significa que es privado. Ni siquiera estoy seguro de que puedas acceder a él con Reflection (aunque valdría la pena intentarlo). Su mejor ClearCache sería agregar un método ClearCache a la fuente (ya que es de código abierto) y enviarlo para su revisión.

Tal vez Sam Saffron o Marc Gravell puedan dar más detalles.


No uso Dapper, pero creo que el siguiente método de extensión debería funcionar con la versión en Repo:

public static class DapperExtensions
{
    public static void ClearTableCache<TDatabase>(this Database<TDatabase> dapperDb)
    {
        var fld = dapperDb.GetType().GetField("tableNameMap", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
        if (fld == null)
            throw new NotSupportedException("Unable to locate Private field tableNameMap");

        var obj = fld.GetValue(null);
        if (obj == null)
            throw new NotSupportedException("Unable to get value from tableNameMap");

        var clear = obj.GetType().GetMethod("Clear");
        if (clear == null)
            throw new NotSupportedException("Unable to locate ConcurrentDictionary<T, U>.Clear");

        clear.Invoke(obj, null);
    }
    public static void ClearParamCache<TDatabase>(this Database<TDatabase> dapperDb)
    {
        var fld = dapperDb.GetType().GetField("paramNameCache", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
        if (fld == null)
            throw new NotSupportedException("Unable to locate Private field paramNameMap");

        var obj = fld.GetValue(null);
        if (obj == null)
            throw new NotSupportedException("Unable to get value from paramNameMap");

        var clear = obj.GetType().GetMethod("Clear");
        if (clear == null)
            throw new NotSupportedException("Unable to locate ConcurrentDictionary<T, U>.Clear");

        clear.Invoke(obj, null);
    }
}

No se ha probado con Dapper, pero probé el principio con POCO. El acceso a las API privadas es peligroso (en el mejor de los casos), pero la reflexión utilizada en este ejemplo de código debería funcionar con la versión actual.



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