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

Posted

技术标签:

【中文标题】将 Dapper 查询映射到对象集合(它本身有几个集合)【英文标题】:Mapping Dapper Query to a Collection of Objects (which itself has a couple of Collections) 【发布时间】:2012-05-09 11:16:37 【问题描述】:

我想执行单个查询(或具有多个结果集的存储过程)。我知道如何使用 Dapper 进行多重映射,但我无法排序如何将两个集合映射到同一个父级。基本上,给定这个对象定义......

class ParentObject

    string Name  get; set; 
    ICollection<ChildObjectOne> ChildSetOne get;set;
    ICollection<ChildObjectTwo> ChildSetTwo  get; set; 


class ChildObjectOne

    string Name  get; set; 


class ChildObjectTwo

    int id  get; set; 
    string LocationName  get; set; 

我希望能够运行以某种方式产生的 Dapper 查询:

IQueryable<ParentObject> result = cnn.Query(
          // Some really awesome dapper syntax goes here
);

【问题讨论】:

【参考方案1】:

不确定您是否不想使用 MultiMapping,但以下是它适用于您的情况的方法。据我所知并阅读 SO,不可能用简单的Query 映射深层嵌套对象图。

 static void Main(string[] args)
        
            var sqlParent = "SELECT parentId as Id FROM ParentTable WHERE parentId=1;";
            var sqlChildOneSet = "SELECT Name FROM ChildOneTable;"; // Add an appropriate WHERE
            var sqlChildTwoSet = "SELECT Id, LocationName FROM ChildTwoTable;"; // Add an appropriate WHERE

            var conn = GetConnection() // whatever you're getting connections with
            using (conn)
            
                conn.Open();
                using (var multi = conn.QueryMultiple(sqlParent + sqlChildOneSet + sqlChildTwoSet))
                
                    var parent = multi.Read<ParentObject>().First();
                    parent.ChildSetOne = multi.Read<ChildOne>().ToList();
                    parent.ChildSetTwo = multi.Read<ChildTwo>().ToList();
                
            
        

嵌套对象和 dapper 的类似问题:

https://***.com/search?q=nested+objects+%2B+dapper

【讨论】:

【参考方案2】:

在这种情况下,可以使用IEnumerable&lt;TReturn&gt; Query&lt;TFirst, TSecond, TThird, TReturn&gt;(this IDbConnection cnn, string sql, Func&lt;TFirst, TSecond, TThird, TReturn&gt; map); 方法实现具有一对多关系的对象。但是,您需要对实体进行一些更改才能获得足够的信息。

这里有一些类似问题的 SO 主题。

How do I map lists of nested objects with Dapper

Extension function to make it cleaner

Dapper.Net by example - Mapping Relationships

public class ParentObject

    public ParentObject()
    
        ChildSetOne = new List<ChildObjectOne>();
        ChildSetTwo = new List<ChildObjectTwo>();
    
    // 1) Although its possible to do this without this Id property, For sanity it is advisable.
    public int Id  get; set; 
    public string Name  get; set; 
    public ICollection<ChildObjectOne> ChildSetOne get; private set;
    public ICollection<ChildObjectTwo> ChildSetTwo  get; private set; 


public class ChildObjectOne

    // 2a) Need a ParentId
    public int ParentId  get; set; 
    public string Name  get; set; 


public class ChildObjectTwo

    // 2b) This ParentId is not required but again for sanity it is advisable to include it.
    public int ParentId  get; set; 
    public int id  get; set; 
    public string LocationName  get; set; 


public class Repository

    public IEnumerable<ParentObject> Get()
    
        string sql = 
            @"SELECT 
                p.Id, 
                p.Name, 
                o.Name, 
                o.ParentId, 
                t.Id, 
                t.LocationName, 
                t.ParentId 
            FROM 
                Parent p 
                    LEFT JOIN ChildOne o on o.ParentId = p.Id 
                    LEFT JOIN ChildTwo t on t.ParentId = p.Id 
            WHERE 
                p.Name LIKE '%Something%'";

        var lookup = new Dictionary<int, ParentObject>();
        using (var connection = CreateConnection())
        

            connection.Query<ParentObject, ChildObjectOne, ChildObjectTwo, ParentObject>(
                sql, (parent, childOne, childTwo) =>
                
                    ParentObject activeParent;

                    if (!lookup.TryGetValue(childOne.ParentId, out activeParent)) 
                    
                        activeParent = parent;
                        lookup.add(activeParent.Id, activeParent);
                    

                    //TODO: if you need to check for duplicates or null do so here
                    activeParent.ChildSetOne.Add(childOne);

                    //TODO: if you need to check for duplicates or null do so here
                    activeParent.ChildSetTwo.Add(childTwo);

                );   
        
        return lookup.Values;
    

【讨论】:

以上是关于将 Dapper 查询映射到对象集合(它本身有几个集合)的主要内容,如果未能解决你的问题,请参考以下文章

将 SqlDataReader 的结果映射到对象的最快方法

Dapper-小型ORM之王(C#.NET)

有没有办法使用 Dapper 将列名映射到我的实体的属性?

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

Dapper - 如何将记录作为自定义对象类型返回?

Dapper入门教程——Dapper Query查询