如何选择一对多关系&使用 dapper 一对一地在一起

发布于 2024-11-26 15:43:17 字数 1081 浏览 2 评论 0原文

我有以下类和数据库架构。我正在尝试使用 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; }
}

I have following classes and db schema. I am trying to query this data from database using dapper that would hydrate the full object graph. I looked at various SO question and the test but couldn't really figure out how to do this.

DB Schema

Author
  -AuthorId
  -Name

Post
  -PostId
  -Content
  -AuthorId

Comment
  -PostId
  -CommentId
  -Content

Tag
  -PostId
  -TagId
  -Name

Classes

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; }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

暮倦 2024-12-03 15:43:17

所以我最终做了如下的事情。

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();
        }

So I ended up doing something like the following.

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;
}

Using the above extension as below.

        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();
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文