2017-03-03 37 views
3

我正在C#系統中工作,我需要模擬多對多關係,我想用手建立模型(即我不想使用任何框架)。如何模擬代碼中的多對多關係?

我將通過系統的簡化例子走,然後解釋,然後問題: 我有一個包含 S和作者 s分別可以有很多作者一座圖書館,以及作者也是如此。

public class Book{ 
    public string Title; 
    public List<Author> Authors; 
} 

public class Author{ 
    public string Name; 
    public List<Book> Books; 
} 

現在,如果我想選擇書及其所有的作者;我會寫在的階級是這樣一個功能:

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]將爲空(或默認值)。 所以我不會做一些半動態的事情,並且始終記住從數據庫服務器和客戶端服務器的角度來看 的性能。

希望我明確地表達了我的觀點。謝謝你的時間。

+1

爲什麼一本書* * *的實例能夠與*作者一起查詢*所有*書籍?聽起來你實際上是在尋找一種容納所有書籍的容器。 – HimBromBeere

+0

除此之外,沒有您的代碼顯示如何填充屬於給定Author的'Books',我們不能說您爲什麼爲null。那麼在創建一個新的'Book' /'Author'時你實際上在做什麼? – HimBromBeere

+0

@HimBromBeere,大多數情況下,查詢將加入**書**與**作者** s,我不知道這是否回答了您的問題。 – Symmetric

回答

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 
    } 
+0

謝謝,我不認爲這個問題確實有一個正確的答案,但對我來說這是有道理的。 – Symmetric

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 
0

Author類是直線上升(填充它在構造函數):

公共類作者 { 公共作者(字符串名稱) {Name Name = name; Books = new List(); } public string Name {get;組; } public List Books {get;組; } }

Book類中,我也填充在構造函數中。作爲一種花招,我設置每個Authorthis的書本屬性:

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