Попытка изменить Dapper для поддержки типа ntext в SQL Server CE

Мне нужно поддерживать тип ntext SQL Server CE в Dapper. Здесь есть ветка с описанием проблемы: https://code.google.com/p/dapper-dot-net/issues/detail?can=2&start=0&num=100&q=&colspec=ID%20Type%20Status%20Priority%20Milestone%20Owner%20Summary&groupby=&sort=&id=110

Я попытался изменить Dapper, чтобы использовать решение, аналогичное подходу, используемому в PetaPoco: https://github.com/cyotek/PetaPoco/commit/ea13add473be3899ebb73b463d2aff98f8d6d06e

Изучив исходный код Dapper, я решил, что хороший способ попытаться это сделать — изменить класс DbString. Я изменил метод AddParameter(IDbCommand command, string name) (начиная со строки 3120) на следующее:

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

Мое редактирование — это часть внизу, которая проверяет тип и пытается изменить его на ntext. Однако, когда я запускаю этот код, происходит сбой IIS Express, и asp.net не дает мне никакой полезной информации об отладке. Я попытался запустить его в отладчике, и я получаю ошибку, связанную с повреждением кучи.

Я на неправильном пути здесь? Есть ли лучший способ попробовать что-то подобное в Dapper? Или это что-то, что просто не будет работать из-за того, как генерируется кеш и/или IL? Я надеялся создать для него запрос на вытягивание, если я смогу заставить его работать, но я отказываюсь.


Обновление - я нашел одно потенциальное решение. Я добавил некоторый код в метод AddParameters(IDbCommand command, SqlMapper.Identity identity) класса DynamicParameters. Последние строки метода теперь гласят:

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;

Чтобы использовать это решение, я должен добавить свои параметры как DynamicParameters. Так что это работает, но не самым полезным образом. Я все еще ищу лучшее решение.

Это то, что разработчики Dapper рассмотрят как патч, если я создам запрос на включение?


person John    schedule 22.07.2013    source источник
comment
Это то, что разработчики Dapper рассмотрят как патч, если я создам запрос на включение? Я бы спросил об этом на сайте github. Хотя возможно, есть некоторый шанс, что вопрос никогда не будет здесь виден.   -  person Hogan    schedule 25.07.2013


Ответы (1)


Попробуйте этот метод расширения для любого пакета свойств:

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

Пример использования:

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