#c# #.net #database #sqlite #dapper
#c# #.net #База данных #sqlite #dapper
Вопрос:
У меня есть база данных 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; }
}
Мне нужно вернуть an IEnumerable<Book>
с Book
объектами, содержащими все Author
, Publisher
и Tag
данные для каждого Book
. В настоящее время у меня есть следующий код, который решает проблему получения данных издателя:
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;
}
}
Как получить оставшиеся данные для a Book
(ie Author
и Tag
данные с отношениями «многие ко многим», как показано на схеме)?
Комментарии:
1. Вы имеете в виду получение коллекций
Author
(ов) иTag
(ов) для каждогоBook
внутриGetAllBooks()
?2. @LuckyBrain это правильно.
Ответ №1:
Было бы не очень эффективно, если бы вы запрашивали книгу за книгой, поэтому я рекомендую сначала запросить все Author
(ы), включая их Book.id
, затем запросить все Tag
(ы), включая их 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
Tag
и т. Д. Но после этого все должно быть в порядке.