最近几天我一直在重构一个项目。该项目使用 Dapper 和 SqlMapper 功能将 Sql 查询的结果映射到对象上。作为我重构的一部分,我将一些对象移动到一个单独的程序集中,这就是事情变得有点不对劲的地方。
public async Task<IEnumerable<HL7Control>> GetHl7ControlRecords()
{
_log.Info("Obtaining a list of required transfer service agents.");
var agentList = StatementBuilder.BuildDapperGetAllHl7ControlRecords();
return await SqlMapper.QueryAsync<HL7Control>(_db, agentList.Sql,agentList.Param);
}
这不断抛出一个 RuntimeBinder 异常,说 'QueryAsync<>' 不是 SqlMapper 的成员。这是已经运行了六个月以上的代码。
我终于找到了问题所在,我很感激其他人的一些想法。“解决方案”是用浏览引用替换对包含“HL7Control”的程序集的项目引用(即;在项目文件中<Project Reference Include...>
。<Reference Include...>
该解决方案由 vs2015 构建,并以 .NET4.6 为目标,但以 .NET4.0 为目标的新程序集除外。
欢迎任何想法,因为当我不理解“修复”时我会不高兴。
谢谢。
更新 1. 更多信息。我忽略了 agentList 不仅名字不好,而且实际上是一个类:
public class DapperStatement
{
public string Sql { get; }
public dynamic Param { get; }
public DapperStatement(string sql, dynamic param)
{
Sql = sql;
Param = param;
}
}
正是因为 Param 是动态的,才涉及到 RuntimeBinder。现在我知道动态不会跨越程序集边界,这是我在重构期间必须解决的其他问题。但是在这种情况下,尽管 DapperStatement是在不同的程序集中定义的,但对象实例并未穿过程序集边界。DapperStatement 总是在另一个程序集中使用它。
另请注意, SqlMapper.Query<> 始终有效,因此显然异步是其中的一个因素。
我还一夜之间重新启动了我的机器并从头开始重建,但问题仍然存在。
哦,将新程序集更改为 .NET4.6 不会改变任何东西(除了破坏正在为其开发的外部客户端项目,哈哈)。
更新 2. 问题似乎特定于 Dapper。进一步解释需要更多细节,所以这里是:最初我们有一个包含多个项目的解决方案。其中一个项目(项目 A)使用 Dapper 来访问和操作一些 SQL 表。然后其他几个项目依赖于此。
同时,另一个外部项目需要访问相同的表,但使用的是 DevExpress XPO。所以我这周一直在做的是移动一些东西,以便 XPO 不再访问这些表。原始的 Dapper 代码做了更多的工作,所以我们决定只删除外部项目需要的东西。这给我们留下了两个使用 Dapper 来操作 SQL 数据库的程序集。看起来我看到的问题是,在那种情况下,有一个项目参考而不是浏览参考会把事情搞砸。
今天早上,我从新项目中删除了 Dapper 引用,突然旧代码再次与浏览器引用一起工作(只要避免我不得不破解的调用)。