2012-05-09 80 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; 
    } 
}