使用 Dapper 映射嵌套对象列表

Posted

技术标签:

【中文标题】使用 Dapper 映射嵌套对象列表【英文标题】:Map lists of nested objects with Dapper 【发布时间】:2015-08-14 09:52:43 【问题描述】:

我正在使用 Dapper,我有这样的课程:

public class Article
   public int Id  get; set; 
   public string Descriptionget;set;
   public Group Group  get; set; 
   public List<Barcode> Barcode get;set;
   ...


public class Group
   public int Id  get; set; 
   public string Description get;set;


public class Barcode
   public int Id  get; set; 
   public string Codeget;set;
   public int IdArticle  get; set; 
   ...

我可以获取有关文章的所有信息,但我想知道是否可以通过一次查询获取每篇文章的条形码列表。其实我做的是这样的:

string query = "SELECT * FROM Article a " +
"LEFT JOIN Groups g ON a.IdGroup = g.Id ";

arts = connection.Query<Article, Group, Article>(query,
    (art, gr) =>
     art.Group = gr;  return art; 
    , null, transaction).AsList();

我还找到了一个很好的解释here,但我不明白如何在我的情况下使用它,因为我也有 Group 类。 我应该如何使用 Dapper 执行此操作,是否有可能或唯一的方法是执行不同的步骤? 谢谢

【问题讨论】:

【参考方案1】:

QueryMultiple 是你的朋友

var query = @"
select a.*, g.* from Article a left join Groups g on g.Id = a.IdGroup    
select * from Barcode";
//NOTE: IdGroup should exists in your Article class.
IEnumerable<Article> articles = null;
using (var multi = connection.QueryMultiple(query))
    articles = multi.Read<Article, Group, Article>((a, g)=>
             a.Group = g; return a; );
    if (articles != null) 
      var barcodes = multi.Read<Barcode>().ToList();
      foreach(var article in articles)           
        article.Barcode = barcodes.Where(x=>x.IdArticle == article.Id).ToList(); 
      
    

这可能不好玩,特别是如果您的查询中没有任何过滤器。但我怀疑你会退回所有文章。在这种情况下,您可以像这样(编辑的 sql)>select * from Barcode where Id in @ids 过滤条形码。然后在 QueryMultiple 中包含参数ids(文章 ID 列表)。

选项2

或者您可以只进行单独的查询:

var query = "select a.*, g.* from Article a left join Groups g on g.Id = a.IdGroup";
var articles = connection.Query<Article, Group, Article>(query,
    (a,g)=>  a.Group = g; return g; ).ToList();
query = "select * from Barcode where IdArticle IN @articleIds";
var articleIds = articles.Select(x=>x.Id);
var barcodes = connection.Query<Barcode>(query, new  articleIds );
foreach(var article in articles)           
    article.Barcode = barcodes.Where(x=>x.IdArticle == article.Id);

我更喜欢第一个选项。

【讨论】:

嗨,冯,在“var articleIds =articles.Select(x=>x.Id);”行的第二个选项上不可能做选择出现错误信息。如果不可能,你是怎么做到的? 我不是 100%,但我知道如果 SELECT 没有结果,Dapper 会返回一个空列表。所以.Select(expression) 不应该抛出空异常。您遇到了什么错误? 不是错误,它看起来像文章。选择选项“选择”不会出现在我可以对文章执行的操作列表中。 代码中的 articles 是一个 IEnumerable 对象。如果你有一个using System.Linq,那么一个.Select 应该可以工作。 哦,我忘了检查“使用 System.Linq;”。它现在有效!谢谢

以上是关于使用 Dapper 映射嵌套对象列表的主要内容,如果未能解决你的问题,请参考以下文章

嵌套多映射 Dapper 分页查询中的重复字段名称问题

Dapper 映射结果列表

Dapper 可以返回映射对象和其他非映射值吗?

为啥我从 Dapper 返回的对象具有 null 和默认属性值?

将 Dapper 查询映射到对象集合(它本身有几个集合)

如何使用从 Flutter 中的 json 解析的嵌套映射列表中的函数创建对象