【发布时间】:2011-12-13 15:35:41
【问题描述】:
给定一个值数组,我想创建一个具有基于这些值的属性的匿名对象。属性名称只是 "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 语句。这些方法通常将string 用于sql 语句,将params 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 的问题。
按照@Paolo Tedesco 的要求使用DynamicParameter 类添加代码。
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 属性显示没有为命令配置的参数。
【问题讨论】:
-
是的,你在滥用 DynamicParameter,见第 243 行:code.google.com/p/dapper-dot-net/source/browse/Tests/Tests.cs
-
另外,
IDynamicParamters为您提供绝对的灵活性。为了小巧玲珑的好处,你永远不需要烘焙匿名类型,作为一种你可以的学习体验,但这不值得付出努力。特别是,如果你真的想使用 emit,你可以从 ICollection 中烘焙一个强类型。
标签: c# anonymous-types dapper