我有一些函数,其原型看起来像这样:public void doThings(string sql, dynamic dParams);
它使用这些参数进行某种SQL查询。我没有写它,但我必须使用它。当我做这样的事情时它工作正常:
doThings("select * from SomeTable where myval1=@v1 and myval2=@v2",
new
{
v1 = new Dapper.DbString()
{
Value = "yay",
IsAnsi = true,
Length = 50
},
v2 = new Dapper.DbString()
{
Value = "really",
IsAnsi = true,
Length = 32
}
});
但是当我第一次将动态参数放入ExpandoObject时:
dynamic dynParams = new ExpandoObject();
dynParams.v1 = new Dapper.DbString()
{
Value = "yay",
IsAnsi = true,
Length = 50
}
doThings("query here", dynParams);
然后查询不返回任何结果。我不想打电话给doThings()
,并写了new
阻止了十次不同的情况,我可能想查询myval2
或myval3
等等。有什么特别的方式我应该通过ExpandoObject
,或者其他一些方式我应该这样做一般吗?
默认情况下,Dapper不支持Expandos,但您可以将expando传递给Dictionary<string,object>
的构造函数,然后将其作为动态参数传递。
当你写道时,看起来doThings
正在使用反射来获得所需的值:
new {
v1 = 1,
v2 = "foo"
}
你正在创建具有两个属性v1
和v2
的类型,但是当你使用ExpandoObject
时,你不会向ExpandoObject
添加任何新属性(它的所有魔法行为都是编译器生成的东西)。
如果你想在编译时使用doThing
属性,我知道没有问题。当在运行时知道属性时,我能想到的唯一方法是使用Reflection.Emit
在运行时生成所需的匿名类型。看看this的文章。
正如@Michael B所提到的,Dapper不支持Expandos作为params。
如果您需要动态构建参数集,根据此article,您可以使用DynamicParameters
。
因此,您可以构建一个从dynParams
到DynamicParameters
的翻译器,它看起来像:
dynamic dynParams = new ExpandoObject();
dynParams.v1 = new Dapper.DbString()
{
Value = "yay",
IsAnsi = true,
Length = 50
};
var parameters = new Dapper.DynamicParameters();
((ExpandoObject)dynParams).ToList().ForEach(kvp => parameters.Add(kvp.Key, kvp.Value));
它认为这可能是一个很好的功能。