我正在使用一种方法,它的返回值是IEnumerable<dynamic>
。在运行时,对于特定的调用,它会返回List<Dapper.SqlMapper.FastExpando>
。
var x0 = repo.Find(proc, param);
//x0 runtime type is {List<Dapper.SqlMapper.FastExpando>}
LINQPad.Extensions.Dump
表明 x0
的运行时类型是:List<IDictionary<String, Object>>
,但我看起来无法转换为 List<IDictionary<String, Object>>
。以下是 Linqpad Dump 的截图:
最终我需要将每个字典的值连接到单个 IEnumerable<DateTime>
中。
IEnumerable<DateTime> GetDates(int productId)
{
const string proc = "[dbo].[myproc]";
dynamic param = new { Id = "asdf" };
var x0 = repo.Find(proc, param);
//...
//linq conversion from x0 to IEnumerable<DateTime> here.
}
我遇到的错误
List<IDictionary<String, Object>> x5 = repo.Find(proc, param);
结果是:
RuntimeBinderException: Cannot implicitly convert type 'object' to
'System.Collections.Generic
.List<System.Collections.Generic.IDictionary<string,object>>'.
An explicit conversion exists (are you missing a cast?)
背景:我正在使用 Dapper
包装器,但无法更改返回非规范化结果的数据库表/存储过程。该存储过程返回 100 行 1 个数据元素的结果,而不是返回 1 行 100 列。我想避免创建一个表示这 100 列的类,并想利用 Dapper
的自动能力通过 columnName,columnValue 的 IDictionary 将列数据转置为行。
更新:似乎这是一个动态参数的问题。当内联指定时,它可以正常工作。如果在本地指定,然后作为参数传递,则会失败。
IEnumerable<DateTime> GetDates(int productId)
{
const string proc = "[dbo].[myproc]";
dynamic param = new { Id = "asdf" };
//next line throws RuntimeBinderException: 'object' does not
//contain a definition for 'First'.
//IDictionary<String, object> x0 = repo.Find(proc, param).First();
//this succeeds:
IDictionary<String, object> x0 = repo.Find(proc, new { Id = "asdf" }).First();
IEnumerable<DateTime> qry2
= x0.Values.AsQueryable()
.Where(x => x != null)
.Select(x => (DateTime) x);
return qry2;
}
以下是Find
和Query
的签名:
//Repository::Find
public IEnumerable<dynamic> Find(string procName, object param = null)
//Dapper SqlMapper::Query
public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
repo.Find
返回一个对象,但它可以(而且应该)被更改为返回IEnumerable<IDictionary<string, object>>
,这是Dapper的Query
方法的返回类型。FastExpando
(在当前源代码中更改为DapperRow
)实现了IDictionary<string, object>
。 - Gert ArnoldDapper
包装器的微妙问题。它的签名是public IEnumerable<dynamic> Find(string procName, object param = null)
,而 Dapper 的签名是public static IEnumerable<dynamic> Query(this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)
,因此似乎在参数param
上进行了从object
到dynamic
的类型转换。我认为将包装器签名更改为dynamic param
应该可以解决这个问题。 - Jay Walker.Cast<IDictionary<String, Object>>()
应该可以工作(Servy 的回答)。 - Gert ArnoldFind
函数。 - Gert Arnold