2012-10-19 23 views
19

複数の結果セットを返すストアドプロシージャがあります。私はこれをdapperで実行しています。QueryMultipleを使用したDapperマルチマッピング

結果セットの1つは、Personが多数のチェックを持つことができるPerson JOINチェックです。

最後の目標は、チェックオブジェクトのコレクションを持つ別個の人物オブジェクトを持つことです。

QueryMutlipleは私にSqlmapper.GridReaderを与えます。 SqlMapper.GridReader.Read()のオーバーロードには、Func<TFirst, TSecond, TReturn>が必要です。

これを使用する方法の例はありますか?

答えて

5

は、ここで私が働いてそれを得た方法は次のとおりです。コメントが言う

var q = _sqlConnection.QueryMultiple("MySproc", 
            myParams, 
            commandType: CommandType.StoredProcedure); 
var set1 = q.Read<Set1Type>(); 

var set2Func = new Func<Person, Check, Person>((p, c) => { 
    p.CheckAlert = c; 
    return p; 
}); 

var set2 = q.Read(set2Func, "CheckId") 
      .GroupBy(x => x.PersonId) 
      .Select(x => { 
       var person = x.First(); 
       person.Checks = x.Select(p => p.Check).ToArray(); 
       person.Check = null; // i really don't like this 
       return person; 
      }) 
      .ToArray(); 

として、私はPersonオブジェクト上の不要なチェックプロパティを好きではありません。

私はまだこれを行うより良い方法を聞きたいと思います。

+2

+1を(NB私は。DapperのGitHubのプロジェクトに関するan issueとしてこれを調達している)が、あなたはそれを行うには良い方法を探しているなら、それは* *答えとしてこれを受け入れない価値があるかもしれ、未回答の質問がより注意を引くように思われるからです。 – dumbledad

+0

"CheckId"とは何ですか?どこから取得していますか? – dumbledad

+0

これは、[splitOn:](http://stackoverflow.com/a/7478958/575530)のパラメータ – dumbledad

4

ここに私が使用したソリューションのバージョンがあります。私は、プロパティをnullに設定するのではなく、継承階層を使用してRonnieがhis answerで提起した問題を横断しましたが、それはほとんど同じことになります。

ここにSQLがあります:ユーザーにはアイテムとコレクションがあり、アイテムはコレクションに含めることができます。

CREATE TABLE Users 
(id UNIQUEIDENTIFIER DEFAULT (NEWID()) NOT NULL, 
name NVARCHAR (MAX) NULL, 
email NVARCHAR (128) NULL, 
PRIMARY KEY (id)) 

CREATE TABLE Items 
(id UNIQUEIDENTIFIER DEFAULT (NEWID()) NOT NULL, 
userId UNIQUEIDENTIFIER NOT NULL, 
name NVARCHAR (MAX) NULL, 
description NVARCHAR (MAX) NULL, 
PRIMARY KEY (id), 
FOREIGN KEY (userId) REFERENCES Users (id)) 

CREATE TABLE Collections 
(id UNIQUEIDENTIFIER DEFAULT (NEWID()) NOT NULL, 
userId UNIQUEIDENTIFIER NOT NULL, 
name NVARCHAR (MAX) NULL, 
layoutSettings NVARCHAR (MAX) NULL, 
PRIMARY KEY (id), 
FOREIGN KEY (userId) REFERENCES Users (id)) 

CREATE TABLE CollectedItems 
(itemId UNIQUEIDENTIFIER NOT NULL, 
collectionId UNIQUEIDENTIFIER NOT NULL, 
PRIMARY KEY CLUSTERED (itemId, collectionId), 
FOREIGN KEY (itemId) REFERENCES Items (id), 
FOREIGN KEY (collectionId) REFERENCES Collections (id)) 

データモデルクラス。コレクションは、複数のクエリを持つDapperマルチマッピングに対処するために私が期待するよりも少し複雑です。

public class User 
{ 
    public Guid Id { get; set; } 
    public string Name { get; set; } 
    public string Email { get; set; } 
    public List<Item> Items { get; set; } 
    public List<Collection> Collections { get; set; } 
} 

public class Item 
{ 
    public Guid Id { get; set; } 
    public Guid UserId { get; set; } 
    public string Name { get; set; } 
    public string Description { get; set; } 
} 

public class CoreCollection 
{ 
    public Guid Id { get; set; } 
    public Guid UserId { get; set; } 
    public string Name { get; set; } 
    public string LayoutSettings { get; set; } 
} 

public class PartialDataCollection : CoreCollection 
{ 
    public Guid ItemId { get; set; } 
} 

public class Collection : CoreCollection 
{ 
    public List<Guid> ItemIds { get; set; } 
} 

public class CollectedItem 
{ 
    public Guid ItemId { get; set; } 
    public Guid CollectionId { get; set; } 
    public DateTime CreatedAt { get; set; } 
} 

最後に、我々は複数のクエリ私は追加することから私の答えに追加の複雑さが心配だロニーはhis answerperson.Check = nullの設定について気になる

[Route("GetUser/{id}")] 
public User GetUser(Guid id) 
{ 
    var sql = @"SELECT * FROM Users WHERE id = @id 
       SELECT * FROM Items WHERE userId = @id 
       SELECT * FROM Collections 
        LEFT OUTER JOIN CollectedItems ON Collections.id = CollectedItems.collectionId 
        WHERE userId = @id"; 
    using (var connection = new SqlConnection(ConnectionString)) 
    { 
     var multi = connection.QueryMultiple(sql, new { id = id }); 
     var user = multi.Read<User>().Single(); 
     var items = multi.Read<Item>().ToList(); 
     var partialDataCollections = multi.Read<PartialDataCollection, CollectedItem, PartialDataCollection>(AddCollectedItem, splitOn: "itemId").ToList(); 

     user.Items = items; 

     user.Collections = partialDataCollections.GroupBy(
      pdc => pdc.Id, 
      (key, group) => new Collection 
      { 
       Id = key, 
       UserId = group.First().UserId, 
       Name = group.First().Name, 
       LayoutSettings = group.First().LayoutSettings, 
       ItemIds = group.Select(groupMember => groupMember.ItemId).ToList() 
      }).ToList(); 

     return user; 
    } 
} 

private PartialDataCollection AddCollectedItem(PartialDataCollection collection, CollectedItem collectedItem) 
{ 
    if (collection != null && collectedItem != null) 
    { 
     collection.ItemId = collectedItem.ItemId; 
    } 
    return collection; 
} 

とDapperのマルチマッピングを使用して、コントローラのメソッドを持っています私のモデルにPartialDataCollectionクラス。しかし、私はその周りに簡単な方法を見ることはできません。

関連する問題