2015-09-25 5 views
1

Только начал работать с Dapper (от NuGet) и не мог понять следующее:Использование численных параметров заполнителей в Dapper

Это работает:

_connection.Query<MySalesPerson>(@"select * from Sales.SalesPerson where territoryId = @id", 
        new {id = territory.TerritoryID}); 

Это не работает:

_connection.Query<MySalesPerson>(@"select * from Sales.SalesPerson where territoryId = @0", 
        new {id = territory.TerritoryID}); 

Таким образом, это не занимает числовые заполнители, это стандартное поведение или я что-то пропускаю. То же работает, как ветер с PetaPoco

ответ

1

Dapper использует объект (а не список) для параметров запроса. Это означает, что он не может (надежно) использовать индексы для получения значений свойств (потому что формально порядок свойств в объекте не указан).

Подробно вы должны проверить метод CreateParamInfoGenerator(), испускаемый код использует GetProperties(), чтобы прочитать все общедоступные параметры вашего объекта. Существует не так много, что вы можете сделать, если вы не вилки и изменить его.

код для преобразования индекса параметра для имени свойства прост, упорядочение свойства может быть достигнуто с кодом от C# Get FieldInfos/PropertyInfos in the original order?

Обратите внимание, что GetProperties() не поддерживает сложные использования (например, реализующую IDynamicMetaObjectProvider для отображения имен свойств индексов однако вы Обратите внимание, что ограничения имени члена задаются языком, а не CLR или CIL, тогда вы можете создать тип со свойствами, имя которых является цифрой. Это доказательство концепции :

object CreatePropertiesFromValues(params object[] args) { 
    // Code to emit new type... 

    int index = 0; 
    foreach (object arg in args) { 
     var name = index.ToString(); 
     var type = typeof(object); // We don't need strongly typed object! 
     var field = typeBuilder.DefineField("_" + name, type, FieldAttributes.Private); 

     var property = typeBuilder.DefineProperty(name, PropertyAttributes.HasDefault, type, null); 

     var method = typeBbuilder.DefineMethod("get_" + name, 
      MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, 
      type, Type.EmptyTypes); 

     var generator = method.GetILGenerator(); 
     generator.Emit(OpCodes.Ldarg_0); 
     generator.Emit(OpCodes.Ldfld, field); 
     generator.Emit(OpCodes.Ret); 

     property.SetGetMethod(method); 

     ++index; 
    } 

    // Code to create an instance of this new type and to set 
    // property values (up to you if adding a default constructor 
    // with emitted code to initialize each field or using _plain_ 
    // Reflection). 
} 

Теперь вы можете использовать его как это:

_connection.Query<MySalesPerson>(@"select * from Sales.SalesPerson where territoryId = @0", 
    CreatePropertiesFromValues(territory.TerritoryID)); 

Ну ... это всегда смешно играть с отражением Emit, но это очень много работы, чтобы добавить поддержку для позиционных параметров. Может быть, проще изменить код Dapper (даже если эта функция, честно говоря, большой запутанный беспорядок).

В заключительной ноте ... Теперь у нас есть Рослины, то мы можем знать порядок, в котором объявляется свойство (и, возможно, даже больше), однако до сих пор я не играл с ним ...

+0

Спасибо за подробное объяснение, позвольте мне посмотреть, как я могу поместиться в одном и том же материале –

Смежные вопросы