使用ExpandoObject传递动态参数

时间:2013-09-24 16:58:16

标签: c# sql dynamic parameter-passing expandoobject

我有一些函数,其原型看起来像这样: 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阻止十次写入十个不同的情况,我可能要查询myval2myval3等等。是否有一些特殊方式我应该通过ExpandoObject,或者其他一些方式我应该这样做?

3 个答案:

答案 0 :(得分:3)

默认情况下,Dapper不支持Expandos,但您可以将expando传递给Dictionary<string,object>的构造函数,然后将其作为动态参数传递。

答案 1 :(得分:1)

当你写下来时,看起来doThings正在使用反射来获取所需的值:

new { 
    v1 = 1,
    v2 = "foo"
}

您正在创建包含两个属性v1v2的类型,但是当您这样做时 使用ExpandoObject你的不会ExpandoObject添加任何新属性(它的所有神奇行为都是编译器生成的东西)。

如果你想在编译时使用已知属性的doThing,我知道没有 问题。在运行时知道属性时,我能想到的唯一方法是使用Reflection.Emit在运行时生成所需的匿名类型。查看this文章。

答案 2 :(得分:1)

正如@Michael B所提到的,Dapper不支持Expandos作为参数。

如果您需要动态构建参数, 根据此article,您可以使用DynamicParameters

因此,您可以构建从dynParamsDynamicParameters的翻译器,它看起来像:

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

它认为这可能是一个很好的功能。