如何创建一个动态确定的属性名称的匿名对象?

anonymous-types c# dapper

给定一个值数组,我想创建一个具有基于这些值的属性的匿名对象。属性名称只是"pN" ,其中N是数组中值的索引。

例如,给定

object[] values = { 123, "foo" };

我想创建一个匿名对象

new { p0 = 123, p1 = "foo" };

我能想到的做到这一点的唯一方法是使用一个switch或者if链最多的参数,以支持一个合理的数字,但我想知道如果有一个更优雅的方式来做到这一点:

object[] parameterValues = new object[] { 123, "foo" };
dynamic values = null;

switch (parameterValues.Length)
{
    case 1:
        values = new { p0 = parameterValues[0] };
        break;
    case 2:
        values = new { p0 = parameterValues[0], p1 = parameterValues[1] };      
        break;
    // etc. up to a reasonable # of parameters
}

背景

我有一组现有的方法来对数据库执行sql语句。这些方法通常采用sql语句的stringparams object[] (如果有的话)。理解是如果查询使用参数,它们将被命名为@p0, @p1, @p2, etc.

例:

public int ExecuteNonQuery(string commandText, CommandType commandType, params object[] parameterValues) { .... }

这将被称为:

db.ExecuteNonQuery("insert into MyTable(Col1, Col2) values (@p0, @p1)", CommandType.Text, 123, "foo");

现在我想在这个类中使用Dapper来包装和公开Dapper的Query<T>方法,并以与现有方法一致的方式进行,例如:

public IEnumerable<T> ExecuteQuery<T>(string commandText, CommandType commandType, params object[] parameterValues) { .... }

但Dapper的Query<T>方法获取匿名对象中的参数值:

var dog = connection.Query<Dog>("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid }); 

导致我关于创建匿名对象以将参数传递给Dapper的问题。


添加使用的代码DynamicParameter类由@Paolo特德斯科的要求。

string sql = "select * from Account where Id = @p0 and username = @p1";
dynamic values = new DynamicParameter(123, "test");
var accounts = SqlMapper.Query<Account>(connection, sql, values);

在Dapper的SqlMapper.cs文件的第581行引发异常:

using (var reader = cmd.ExecuteReader())

并且异常是SqlException

必须声明标量变量“@ p0”。

并检查cmd.Parameters属性显示没有为该命令配置参数。

热门答案

你滥用Dapper,你永远不需要这样做,而是实现IDynamicParameters或使用特定的极其灵活的DynamicParameters类。

尤其是:

string sql = "select * from Account where Id = @id and username = @name";
var values = new DynamicParameters();
values.Add("id", 1);
values.Add("name", "bob");
var accounts = SqlMapper.Query<Account>(connection, sql, values);

DynamicParameters可以在构造函数中接受匿名类。您可以Concat的DynamicParameters使用AddDynamicParams方法。

此外,对匿名类型没有严格的依赖性。 Dapper将允许混凝土类型作为参数,例如:

class Stuff
{
   public int Thing { get; set; }
}

...

cnn.Execute("select @Thing", new Stuff{Thing = 1});

凯文有一个类似的问题: 寻找一种快速简便的方法来合并POCO上的所有属性 - DynamicParameters在这里完美运行,而不需要魔术箍跳跃。



许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因
许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因