Jef*_*ata 16 c# anonymous-types 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
}
Run Code Online (Sandbox Code Playgroud)
背景
我有一组现有的方法来对数据库执行sql语句.这些方法通常采用strings语句和a params object[]参数(如果有).理解是如果查询使用参数,它们将被命名@p0, @p1, @p2, etc..
例:
public int ExecuteNonQuery(string commandText, CommandType commandType, params object[] parameterValues) { .... }
Run Code Online (Sandbox Code Playgroud)
这将被称为:
db.ExecuteNonQuery("insert into MyTable(Col1, Col2) values (@p0, @p1)", CommandType.Text, 123, "foo");
Run Code Online (Sandbox Code Playgroud)
现在我想在这个类中使用Dapper来包装和公开Dapper的Query<T>方法,并以与现有方法一致的方式这样做,例如:
public IEnumerable<T> ExecuteQuery<T>(string commandText, CommandType commandType, params object[] parameterValues) { .... }
Run Code Online (Sandbox Code Playgroud)
但Dapper的Query<T>方法采用匿名对象中的参数值:
var dog = connection.Query<Dog>("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });
Run Code Online (Sandbox Code Playgroud)
导致我关于创建匿名对象以将参数传递给Dapper的问题.
DynamicParameter根据@Paolo Tedesco的要求使用类添加代码.
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);
Run Code Online (Sandbox Code Playgroud)
在Dapper的SqlMapper.cs文件的第581行引发异常:
using (var reader = cmd.ExecuteReader())
Run Code Online (Sandbox Code Playgroud)
而例外是SqlException:
必须声明标量变量"@ p0".
并检查cmd.Parameters属性显示没有为命令配置参数.
Sam*_*ron 14
你滥用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);
Run Code Online (Sandbox Code Playgroud)
DynamicParameters可以在构造函数中接受一个匿名类.您可以DynamicParameters使用该AddDynamicParams方法进行连接.
此外,对匿名类型没有严格的依赖性.Dapper将允许混凝土类型作为参数,例如:
class Stuff
{
public int Thing { get; set; }
}
...
cnn.Execute("select @Thing", new Stuff{Thing = 1});
Run Code Online (Sandbox Code Playgroud)
Kevin有一个类似的问题:寻找一种快速简便的方法来合并POCO上的所有属性 - DynamicParameters在这里也可以完美地工作,而不需要魔术箍跳.
不完全是一个匿名对象,但是如何实现一个DynamicObject,它根据数组中的值返回p1 ... pn的值?这会与Dapper一起工作吗?
例:
using System;
using System.Dynamic;
using System.Text.RegularExpressions;
class DynamicParameter : DynamicObject {
object[] _p;
public DynamicParameter(params object[] p) {
_p = p;
}
public override bool TryGetMember(GetMemberBinder binder, out object result) {
Match m = Regex.Match(binder.Name, @"^p(\d+)$");
if (m.Success) {
int index = int.Parse(m.Groups[1].Value);
if (index < _p.Length) {
result = _p[index];
return true;
}
}
return base.TryGetMember(binder, out result);
}
}
class Program {
static void Main(string[] args) {
dynamic d1 = new DynamicParameter(123, "test");
Console.WriteLine(d1.p0);
Console.WriteLine(d1.p1);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
20558 次 |
| 最近记录: |