Dapper - 使用一对多和多对多关系的数据库查询创建对象

Dapper - creating objects with queries on database with one-to-many and many-to-many relationships

我有一个 Sqlite 数据库,其部分模式是:

代码中,类代表的数据如下(简化):

public Book : Item
{
    public ICollection<Tag> Tags { get; set; }
    public ICollection<Author> Authors { get; set; }
    public Publisher publisher { get; set; }
    // other properties...
}

public class Publisher
{
    public ICollection<Book> Books { get; set; }
    // other properties...
}

public class Author
{
    public ICollection<Author> Authors { get; set; }
}

public class Tag
{
    public ICollection<Item> Items { get; set; }
}

我需要 return 一个 IEnumerable<Book>,其中 Book 个对象包含每个对象的所有 AuthorPublisherTag 数据Book。目前,我有如下代码,解决了获取publisher数据的问题:

public IEnumerable<Book> GetAllBooks()
{
    using (var db = new SqliteConnection(connectionString)
    {
        var sql = "SELECT * FROM Books as B " +
                  "INNER JOIN Publishers AS P On B.publisherId = P.id;";
        var allBooks = db.Query<Book, Publisher, Book>(sql, (book, publisher) =>
        {
             book.publisher = publisher;
             return book;
        });
        return allBooks;
    }
}

如何获取 Book 的剩余数据(即 AuthorTag 具有架构中所见的多对多关系的数据)?

如果你一本书一本书地查询,效率不会很高,所以我的建议是先查询所有 Author(s),包括他们的 Book.id,然后查询所有 Tag (s) 包括他们的 Book.id,然后使用 LINQ 来匹配 Book.id 这些查询的结果,如下所示:

public IEnumerable<Book> GetAllBooks()
{
    using (var db = new SqliteConnection(connectionString))
    {
        var authorsSql = "SELECT A.*, B.id AS BookId FROM Books as B " +
                         "INNER JOIN Book_Author AS B2A On B.id = B2A.bookId " +
                         "INNER JOIN Author A On B2A.authorId = A.id;";
        var allAuthorsWithBookId = db.Query<dynamic>(authorsSql).AsList();

        var tagsSql = "SELECT T.*, B.id AS BookId FROM Books as B " +
                      "INNER JOIN Book_Tag AS B2T On B.id = B2T.bookId " +
                      "INNER JOIN Tags T On B2T.tagId = T.id;";
        var allTagsWithBookId = db.Query<dynamic>(tagsSql).AsList();

        var sql = "SELECT * FROM Books as B " +
                  "INNER JOIN Publishers AS P On B.publisherId = P.id;";
        var allBooks = db.Query<Book, Publisher, Book>(sql, (book, publisher) =>
        {
            book.publisher = publisher;
            book.Authors = allAuthorsWithBookId.Where(row => row.BookId == book.id).Select(row => new Author{ id = row.id, name = row.name }).AsList();
            book.Tags = allTagsWithBookId.Where(row => row.BookId == book.id).Select(row => new Tag{ id = row.id, name = row.name }).AsList();
            return book;
        });
        return allBooks;
    }
}

您需要更正一些拼写错误和结构代码(例如 using 末尾的括号)以及 类 Author、[=13] 中缺少的一些属性=],等等,但之后应该就可以了。