Intentando modificar Dapper para admitir el tipo de texto de SQL Server CE

dapper sql-server-ce

Pregunta

Tengo una necesidad de apoyar de SQL Server CE ntext tipo de Dapper. Aquí hay un hilo que describe el problema: https://code.google.com/p/dapper-dot-net/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Priority%20Milestone % 20Propietario% 20Summary & groupby = & sort = & id = 110

Intenté modificar Dapper para utilizar una solución similar al enfoque utilizado en PetaPoco: https://github.com/cyotek/PetaPoco/commit/ea13add473be3899ebb73b463d2aff98f8d6d06e

Después de echar un vistazo a la fuente de Dapper, decidí que una buena manera de intentar esto podría ser modificar la clase DbString . Cambié el AddParameter(IDbCommand command, string name) (comenzando en la línea 3120) a lo siguiente:

public void AddParameter(IDbCommand command, string name)
{
            if (IsFixedLength && Length == -1)
            {
                throw new InvalidOperationException("If specifying IsFixedLength,  a Length must also be specified");
            }
            var param = command.CreateParameter();
            param.ParameterName = name;
            param.Value = (object)Value ?? DBNull.Value;
            if (Length == -1 && Value != null && Value.Length <= 4000)
            {
                param.Size = 4000;
            }
            else
            {
                param.Size = Length;
            }
            param.DbType = IsAnsi ? (IsFixedLength ? DbType.AnsiStringFixedLength : DbType.AnsiString) : (IsFixedLength ? DbType.StringFixedLength : DbType.String);

            if (param.Value != null)
            {
                if (param.Value.ToString().Length + 1 > 4000 && param.GetType().Name == "SqlCeParameter")
                {
                    param.GetType().GetProperty("SqlDbType").SetValue(param, System.Data.SqlDbType.NText, null);  
                }
            }

            command.Parameters.Add(param);
}

Mi edición es la parte hacia abajo que verifica el tipo e intenta cambiarlo a ntext . Sin embargo, cuando ejecuto este código, IIS Express se cuelga y asp.net no me proporciona ninguna información de depuración útil. Intenté ejecutarlo en un depurador y recibí un error relacionado con la corrupción del montón.

¿Estoy en el camino equivocado aquí? ¿Hay alguna forma mejor de intentar algo como esto en Dapper? ¿O es algo que simplemente no va a funcionar debido a la forma en que se genera el caché y / o IL? Tenía la esperanza de crear una solicitud de extracción si conseguía que funcione, pero estoy en huelga.


Actualización: he encontrado una posible solución. AddParameters(IDbCommand command, SqlMapper.Identity identity) un código al AddParameters(IDbCommand command, SqlMapper.Identity identity) en la clase DynamicParameters . Las últimas líneas del método ahora son:

if (s != null)
{
    if (s.Length + 1 > 4000 && p.GetType().Name == "SqlCeParameter")    
    {
        p.GetType().GetProperty("SqlDbType").SetValue(p, SqlDbType.NText, null);
        p.Size = s.Length;
    }
}
if (add)
{
    command.Parameters.Add(p);
}
param.AttachedParam = p;

Para usar esta solución, tengo que agregar mis parámetros como DynamicParameters. Entonces funciona, pero no de la manera más útil. Todavía estoy buscando una mejor solución.

¿Es este el tipo de cosa que los desarrolladores de Dapper considerarían incluir como un parche si creo una solicitud de extracción?

Respuesta popular

Pruebe este método de extensión con cualquier bolsa de propiedades:

    public static class DynamicParametersExtensions
{
    public static DynamicParameters AsDynamic(this object propertyBag) {
        var parameters = new DynamicParameters();
        foreach (var property in propertyBag.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public)) {
            var propertyValue = property.GetValue(propertyBag);
            var propertyValueAsString = propertyValue as string;
            if (propertyValueAsString != null && propertyValueAsString.Length >= 4000) {
                parameters.Add(property.Name, new DbString {
                    Value = propertyValueAsString,
                    Length = propertyValueAsString.Length
                });
            } else {
                parameters.Add(property.Name, propertyValue);
            }
        }
        return parameters;
    }
}

Ejemplo de uso:

connection.Execute(@"UPDATE MyTable SET NTextColumn=@NTextColumn", new { value.NTextColumn }.AsDynamic()); 


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