我有以下类和数据库模式。我试图使用dapper从数据库中查询这些数据,这将使整个对象图水合。我查看了各种SO问题和测试,但无法弄清楚如何做到这一点。
Author
-AuthorId
-Name
Post
-PostId
-Content
-AuthorId
Comment
-PostId
-CommentId
-Content
Tag
-PostId
-TagId
-Name
public class Author
{
public int AuthorId { get; set; }
public string Name { get; set; }
}
public class Tag
{
public int PostId { get; set; }
public int TagId { get; set; }
public string Name { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Content { get; set; }
public int AuthorId { get; set; }
public List<Tag> Tags { get; set; }
public List<Comment> Comments { get; set; }
public Author Author { get; set; }
public Post()
{
this.Comments = new List<Comment>();
this.Tags = new List<Tag>();
}
}
public class Comment
{
public int PostId { get; set; }
public int CommentId { get; set; }
public string Content { get; set; }
}
答案 0 :(得分:5)
所以我最终做了以下的事情。
public static IEnumerable<Post> Map(this SqlMapper.GridReader reader, Func<Post, int> postKey, Func<Comment, int> commentKey, Func<Tag, int> TagKey, Action<Post, IEnumerable<Comment>> addPostComment, Action<Post, IEnumerable<Tag>> addPostTag)
{
var posts = reader.Read<Post>().ToList();
var comments = reader.Read<Comment>().GroupBy(t => commentKey(t)).ToDictionary(g => g.Key, g => g.AsEnumerable());
var tags = reader.Read<Tag>().GroupBy(t => TagKey(t)).ToDictionary(g => g.Key, g => g.AsEnumerable());
var authors = reader.Read<Author>().ToList();
foreach (var post in posts)
{
IEnumerable<Tag> posttags;
if (tags.TryGetValue(postKey(post), out posttags))
{
addPostTag(post, posttags);
}
IEnumerable<Comment> postcomments;
if (comments.TryGetValue(postKey(post), out postcomments))
{
addPostComment(post, postcomments);
}
post.Author = authors.Where(a => a.AuthorId == post.AuthorId).SingleOrDefault();
}
return posts;
}
使用以上扩展名如下。
var query = "SELECT p.* FROM Post p " +
"SELECT c.* FROM Comment c WHERE c.PostId in ( SELECT PostId FROM Post) " +
"SELECT t.* FROM Tag t WHERE t.PostId in ( SELECT PostId FROM Post) " +
"SELECT a.* FROM Author a WHERE a.AuthorId in ( SELECT AuthorId FROM Post) ";
List<Post> result = new List<Post>();
using (var conn = new System.Data.SqlClient.SqlConnection(ConnectionString))
{
conn.Open();
try
{
var posts = conn.QueryMultiple(query)
.Map
(
p => p.PostId,
c => c.PostId,
t => t.PostId,
(p, c) => p.Comments.AddRange(c),
(p, t) => p.Tags.AddRange(t)
);
if (posts != null && posts.Any())
{
result.AddRange(posts);
}
}
catch (Exception)
{
//TODO: Log Exception
throw;
}
conn.Close();
}