Using numerical parameter placeholders in Dapper
刚开始使用Dapper(来自Nuget)工作,却无法找出以下内容:
这有效:
1 2 | _connection.Query<MySalesPerson>(@"select * from Sales.SalesPerson where territoryId = @id", new {id = territory.TerritoryID}); |
这不起作用:
1 2 | _connection.Query<MySalesPerson>(@"select * from Sales.SalesPerson where territoryId = @0", new {id = territory.TerritoryID}); |
因此它不占用数字占位符,这是标准行为,还是我错过了一些东西。与PetaPoco
一样轻而易举
Dapper使用对象(而不是列表)作为查询参数。这意味着它不能(可靠地)使用索引来获取属性值(因为正式地,未指定对象中的属性顺序)。
详细地,您应该检查
将参数索引转换为属性名称的代码很简单,可以使用C#的代码以原始顺序获取FieldInfos / PropertyInfos来实现属性排序?
请注意,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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). } |
现在您可以像这样使用它:
1 2 | _connection.Query<MySalesPerson>(@"select * from Sales.SalesPerson where territoryId = @0", CreatePropertiesFromValues(territory.TerritoryID)); |
好吧...与"反射发射"一起玩总是很有趣,但是要增加对位置参数的支持还需要做很多工作。更改Dapper代码可能更容易(坦白地说,即使该函数造成了很大的麻烦)。
作为最后的说明...现在我们也有了Roslyn,然后我们可能知道声明属性的顺序(甚至可能更多),但是到目前为止,我还没有使用它...