我在C#系统中工作,我需要建模多对多关系,我想手动构建模型(即我不想使用任何框架)。
我将通过一个简化的系统示例,然后解释问题: 我有一个包含 Book 和作者的库,每个 Book 可以有很多作者,同样的适用于作者。
public class Book{
public string Title;
public List<Author> Authors;
}
public class Author{
public string Name;
public List<Book> Books;
}
现在,如果我想与所有作者一起 SELECT 书籍;我会在 Book 的类中编写一个函数,如下所示:
public List<Book> All(){
List<Book> Books = new List<Book>();
Books = //Query that brings all books and its Authors and populate them into the Books list.
}
现在我应该可以这样做:
Book boo = new Book();
List<Book> books = boo.All();
Console.WriteLine(books[0].Authors[0].Name);
但我不能做的是:
Console.WriteLine(books[0].Authors[0].Books[0].Title);
因为在此流程中books[0].Authors[0].Books[0]
将为null(或默认值)。
所以我不会做一些半动态的东西,并且仍然记住表现
数据库服务器和客户端服务器透视图。
希望我明白我的观点。谢谢你的时间。
答案 0 :(得分:0)
我会做这样的事情来模仿数据库n到n的关系:
public class DB
{
public class Book
{
public string Title;
public List<Author> Authors
{
get
{
return
BookAuthor.Connection.Where(ba => ba.Book.Title == this.Title)
.Select(ba => ba.Author)
.ToList();
}
}
public void AddAuthor(Author a)
{
var connection = new BookAuthor(this, a);
if (!BookAuthor.Connection.Exists(c => c.Author.Name == connection.Author.Name &&
c.Book.Title == connection.Book.Title))
BookAuthor.Connection.Add(connection);
}
}
public class Author
{
public string Name;
public List<Book> Books
{
get
{
return
BookAuthor.Connection.Where(ba => ba.Author.Name == this.Name)
.Select(ba => ba.Book)
.ToList();
}
}
public void AddBook(Book b)
{
var connection = new BookAuthor(b, this);
if (!BookAuthor.Connection.Exists(c => c.Author.Name == connection.Author.Name &&
c.Book.Title == connection.Book.Title))
BookAuthor.Connection.Add(connection);
}
}
private class BookAuthor
{
public Book Book { get; set; }
public Author Author { get; set; }
public static List<BookAuthor> Connection { get; } = new List<BookAuthor>();
public BookAuthor(Book book, Author author)
{
Book = book;
Author = author;
}
}
}
public void Run()
{
List<DB.Book> books = new List<DB.Book>()
{
new DB.Book() {Title = "Crime & Punishment"},
new DB.Book() {Title = "Karamazov"}
};
List<DB.Author> authors = new List<DB.Author>()
{
new DB.Author()
{
Name = "Dostoyevsky",
Books = { books[0] }
}
};
authors[0].AddBook(books[1]);
authors[0].AddBook(books[1]); // constraint
List<DB.Book> allBooksOfDostoyevsky = authors[0].Books;
var dost = authors[0].Books[0].Authors[0].Name; // Dostoyevsky
}
答案 1 :(得分:0)
在传统的数据库设计中,n:m关系由三个表组成:
Author -- 1:n --> helper table <-- n:1 -- Book
这就是我要做的,有3个班级,书籍,作者和连接两者的东西:
class Book {
public int ID { get; set; }
public string Title { get; set; }
}
class Author {
public int ID { get; set; }
public string Name { get; set; }
}
class BookAuthorConnections {
public int ID_Book { get; set; }
public int ID_Author { get; set; }
}
...然后制作包含这些类的3个列表,例如:
static void Main(string[] args) {
var authors = new List<Author>() {
new Author() { ID = 1, Name = "Blah" },
new Author() { ID= 2, Name = "Blubb" }
};
var books = new List<Book>() {
new Book() { ID = 1, Title = "Some Book" },
new Book() { ID = 2, Title = "Some other Book"},
new Book() { ID = 3, Title = "Book 3"}
};
var connections = new List<BookAuthorConnections> {
new BookAuthorConnections() { ID_Author = 1, ID_Book = 1 },
new BookAuthorConnections() { ID_Author = 1, ID_Book = 2 },
new BookAuthorConnections() { ID_Author = 2, ID_Book = 2 },
new BookAuthorConnections() { ID_Author = 2, ID_Book = 3 }
};
...然后加入他们,关于作者关系的书籍。使用简单的Where
,您可以访问所需的一切:
var result = books
.Join(connections, book => book.ID, connection => connection.ID_Book, (book, con) => new { book.Title, con.ID_Author, con.ID_Book })
.Join(authors, temp_result => temp_result.ID_Author, author => author.ID, (temp_result, author) => new { author.Name, temp_result.Title, temp_result.ID_Author, temp_result.ID_Book })
.Where(x => x.Title == "Some other Book"); //returns all authors who wrote that book
//.Where(x => x.Author == "...") would return all Books written by that author
//.Where(x => x.ID_Book .... or x.ID_Author would access everything by ID
答案 2 :(得分:0)
让Author
类直接向上(在构造函数中填充它):
公共课作者 { 公共作者(字符串名称) { 名字=姓名; Books = new List(); } public string Name {get;组; } 公共列表簿{get;组; } }
在Book
类中,我也填充了构造函数。作为一种扭曲,我将每个Author
的书籍属性设置为this
:
public class Book
{
public Book(string name, IList<Author> authors)
{
Name = name;
Authors = new List<Author>();
foreach (Author author in authors)
{
author.Books.Add(this);
Authors.Add(author);
}
}
public string Name { get; set; }
public List<Author> Authors { get; set; }
}
代码将类似于:
public void main()
{
Author hermanM = new Author("Herman Melville");
IList<Author> authors = new List<Author>();
authors.Add(hermanM);
Book mobyDick = new Book("Moby-Dick",authors);
string bookTitle = mobyDick.Authors[0].Books[0].Name;
}
任何像这样创建的书都可以通过linq查询选择,或者你想要这样做。此外,链条将是无限的。在这种情况下,我可以选择标题。来自:
string bookTitle = mobyDick.Name;
但我也可以把它拉到其他水平,比如:
string bookTitle = mobyDick.Authors[0].Books[0].Authors[0].Books[0].Authors[0].Books[0];
在这种情况下,只有一本书由一位作者撰写,结果将是相同的。
在下面的示例中。我创建了一个有两本书的图书馆。然后我搜索作者的书籍。
public void BooksByAuthorExample()
{
//Create library
IList<Book> myLibrary = new List<Book>();
//Define first book
Author hermanM = new Author("Herman Melville");
IList<Author> authors = new List<Author>();
authors.Add(hermanM);
Book mobyDick = new Book("Moby-Dick", authors);
//Define second book
Author gamma = new Author("Eric Gamma");
Author helm = new Author("Richard Helm");
Author johnson = new Author("Ralph Johnson");
Author vlissides = new Author("Johm Vlissides");
IList<Author> gangOfFour = new List<Author>() { gamma, helm, johnson, vlissides};
Book designPatterns = new Book("Design Patterns - Elements of Reusable Object-Oriented Software", gangOfFour);
//Add books to the library
myLibrary.Add(mobyDick);
myLibrary.Add(designPatterns);
//Select books written by Richard Helm
IList<Book> searchResult = myLibrary.Where(x => x.Authors.Contains(helm)).ToList();
}