2012-05-09 43 views
4

我想执行一个查询(或带有多个结果集的存储过程)。我知道如何使用Dapper进行多重映射,但我无法排序如何将两个集合映射到同一个父级。基本上,鉴于这一对象定义...将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; } 
} 

我希望能够运行,不知怎的,产生一个小巧玲珑的查询:

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

回答

6

不知道,如果你不希望使用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(); 
       } 
      } 
     } 

嵌套对象和短小精悍的类似问题:

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

2

有可能兑现的对象使用在这种情况下,IEnumerable<TReturn> Query<TFirst, TSecond, TThird, TReturn>(this IDbConnection cnn, string sql, Func<TFirst, TSecond, TThird, TReturn> 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; 
    } 
}