使用ExpandoObject传递动态参数

7

我有一些函数的原型看起来像这样: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()并为可能需要查询myval2myval3等十种不同情况编写new块十次。我应该以某种特殊的方式传递ExpandoObject,还是通常应该以其他方式进行操作?

3个回答

5

Dapper默认不支持Expandos,但是你可以将Expando对象传递给Dictionary<string,object>的构造函数并将其作为动态参数传递。


4

正如 @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));

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


1

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

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

你正在创建具有两个属性v1v2的类型,但是当你使用ExpandoObject时,你的不会ExpandoObject添加任何新属性(它所有的魔法行为都是编译器生成的东西)。
如果你想在编译时知道属性并使用doThing,我理解没有问题。当属性在运行时才能确定时,我唯一能想到的方法是使用Reflection.Emit在运行时生成所需的匿名类型。看看this文章。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接