【问题标题】:How to return dynamic types List<dynamic> with Dapper ORM如何使用 Dapper ORM 返回动态类型 List<dynamic>
【发布时间】:2014-12-26 21:31:25
【问题描述】:

我使用 Dapper.net 已经有一段时间了,它是一个非常好的 ORM 映射器,可以很好地与 .Net 动态类型配合使用。

但我注意到,当 Dapper 从数据库中检索数据时,它会以 DapperRow 类型返回。

有什么方法可以让我以任何其他类型返回它,例如System.Dynamic.ExpandoObject

【问题讨论】:

标签: c# .net orm dapper


【解决方案1】:

当然!

根据 dapper 文档,使用查询方法并获取您的动态:

dynamic account = conn.Query<dynamic>(@"
                    SELECT Name, Address, Country
                    FROM Account
            WHERE Id = @Id", new { Id = Id }).FirstOrDefault();
Console.WriteLine(account.Name);
Console.WriteLine(account.Address);
Console.WriteLine(account.Country);

如您所见,您获得了一个动态对象,并且您可以访问其属性,只要它们在查询语句中定义良好。

如果你省略 .FirstOrDefault(),你会得到一个 IEnumerable&lt;dynamic&gt;,你可以用它做任何你想做的事情。

【讨论】:

  • 在 Oracle 中,相同的查询会生成属性 account.NAMEaccount.ADDRESSaccount.COUNTRY
【解决方案2】:

DapperRow 对象旨在在行之间共享大量状态。例如,如果您获取 40 行,则列名等仅存储一次。如果我们使用ExpandoObject,则需要按行配置。因此,使用DapperRow 作为幕后实现细节是一种刻意提高效率的事情。

请注意,从dynamic API 返回的对象也可以转换为IDictionary&lt;string,object&gt;

然而,我愿意支持 other 支持这种字典用法的类型 - 其中ExpandoObject 是其中之一。所以是的,它可以这样改变:

var rows = conn.Query<ExpandoObject>(...);

有效。它只需要代码来支持它,而该代码目前不存在。所以“不,但也许在未来的版本中”。

另请注意,您根本不需要使用DapperRow...更预期的场景是使用通用 API 来实现您自己的类型。

【讨论】:

  • Hello Marc.Execuse me its old question但我需要知道创建动态行而不是像OP问的那样返回它。我想知道如何将新的动态行 (DapperRow) 添加到动态 Query。它不支持可能是因为 DapperRow 是内部的。并且不能从公共项目中创建?请问你知道怎么做吗?也许支持扩展方法来添加新的空 DapperRow (例如 AddDynamicRow() 仅出现在 List )。谢谢
  • @deveton 这不是一个受支持的场景,并且目前没有添加这样的计划;如果有的话,我们想删除动态的,现在像值元组和记录这样的东西是高度本地数据访问的更好候选者
  • 感谢您的回复。但有时您需要添加新的空行。特别适用于数据源级别的可绑定网格......请问可以为数据网格提供哪些记录和值元组?动态可能是更好的解决方案。所以请如果您在 Dapper 中支持更多动态功能方面付出更多努力,它将帮助很多人......
  • 我还需要知道如果您需要在 List 中添加新的空行,您会怎么做?也许你有很好的细节给你。因为我需要使用 Activator 类来创建集合的第一个 DapperRow 的实例。这很慢谢谢
  • 还有一点你必须注意。带有强类型的 Dapper 是 100% 好的。但为什么我需要创建 100 个 C# 类。只是将它们分配给 SQL-Server?如果我需要添加许多表中可能非常需要的新列。我需要重新构建整个项目并向类添加新列。在动态中,它只需要向 SQL-Server 添加列,它将直接出现在同一个部署的项目中。所以那里有很大的不同。祝您先生添加更多动态功能(很多人要求添加新空行。请不要忘记查看以前的cmets)
【解决方案3】:

我有这个问题,我就这样解决了!

Query() 函数返回一个动态集合,这些动态集合实际上是Dapper.SqlMapper.DapperRow 对象类型。 Dapper.SqlMapper.DapperRow 是私有的。我需要向 Dapper.SqlMapper.DapperRow 对象动态添加属性,但这似乎不起作用。因此,我想将Dapper.SqlMapper.DapperRow 转换为ExpandoObject

我能够像下面这样构建这个通用辅助方法。

public class DapperHelpers
{
     public static dynamic ToExpandoObject(object value)
     {
         IDictionary<string, object> dapperRowProperties = value as IDictionary<string, object>;

         IDictionary<string, object> expando = new ExpandoObject();

         foreach (KeyValuePair<string, object> property in dapperRowProperties)
             expando.Add(property.Key, property.Value);

         return expando as ExpandoObject;
     }
}

然后你可以这样使用:

IEnumerable<ExpandoObject> result = 
           db.SqlConn.Query(sqlScript)
               .Select(x=> (ExpandoObject)ToExpandoObject(x));

参考:dapper-dot-net issues 166

【讨论】:

  • 为什么我们必须将简洁的行显式转换为 Expando 对象,它可以通过以下方法进行转换,对吗? var rows = conn.Query(...);
  • 也许在 Dapper 的下一个版本中可以正常工作,但在我使用的 1.4 版本中,转换后的对象没有任何属性。我从小巧玲珑的问题中找到了这个解决方案。
猜你喜欢
  • 2019-08-13
  • 1970-01-01
  • 1970-01-01
  • 2021-12-29
  • 2023-01-08
  • 2023-01-10
  • 2020-05-19
  • 2018-12-16
  • 2021-08-05
相关资源
最近更新 更多