2017-03-03 6 views
3

Ich arbeite in einem C# -System, wo ich eine Viele-zu-Viele-Beziehung modellieren muss, wo ich die Modelle von Hand erstellen möchte (d. H. Ich möchte keine Frameworks verwenden).Wie modelliert man viele zu viele Beziehungen im Code?

ich durch ein vereinfachtes Beispiel des Systems gehen, und dann erklären, dann Problem: Ich habe eine Bibliothek, die Buch s und Autor s enthält jedes Buch viele Autor s haben, und Das gleiche gilt für die Autor.

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

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

Nun, wenn ich will Bücher mit all ihren Autoren zu SELECT; Ich würde eine Funktion in den Buch s Klasse so etwas schreiben:

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

Nun soll ich in der Lage sein, so etwas zu tun:

Book boo = new Book(); 
List<Book> books = boo.All(); 
Console.WriteLine(books[0].Authors[0].Name); 

Aber was ich nicht tun kann ist:

Console.WriteLine(books[0].Authors[0].Books[0].Title); 

Da in diesem Fluss books[0].Authors[0].Books[0] null sein wird (oder der Standardwert). Also ich werde nicht etwas Semi-Dynamic zu machen und immer noch die Leistung von der Datenbankserver und Client-Server-Perspektive im Auge behalten.

Ich hoffe, ich machte meinen Standpunkt klar genug. Vielen Dank für Ihre Zeit.

+1

Warum sollte eine Instanz von * einem * Buch in der Lage sein, * alle * Bücher zusammen mit einem anderen Autor abzufragen? Klingt, dass du nach einer Art Container suchst, der all deine Bücher enthält. – HimBromBeere

+0

Abgesehen davon, dass Ihr Code nicht zeigt, wie Sie die 'Bücher', die zu einem bestimmten' Autor' gehören, füllen, können wir Ihnen nicht sagen, warum er null ist. Was machst du eigentlich, wenn du ein neues Buch/Autor erstellst? – HimBromBeere

+0

@HimBromBeere, Meistens würde die Abfrage die ** Buch ** s mit ** Autoren ** s verbinden, ich weiß nicht, ob dies Ihre Frage beantwortet hat. – Symmetric

Antwort

0

Ich würde so etwas tun, die Datenbank n zu n-Beziehung zu imitieren:

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

Danke, ich glaube nicht, dass es wirklich eine richtige Antwort für diese Frage gibt, aber für mich macht das Sinn. – Symmetric

0

In der traditionellen Datenbank Design eine n: m-Beziehung besteht aus drei Tabellen:

Author -- 1:n --> helper table <-- n:1 -- Book 

Das ist, was ich würde hier mit 3 Klassen, Buch, Autor und etwas, das beide verbindet:

. .. dann machen 3 Listen, die diese Klassen enthalten, zum Beispiel:

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

... und dann beitreten, Bücher über Verbindungen auf Autoren.Mit einem einfachen Where Sie alles zugreifen können Sie wollen:

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

die Author Klasse Lassen Sie gerade nach oben sein (füllen Sie es im Konstruktor):

public class Autor { public Autor (string name) { Name = Name; Bücher = neue Liste(); } öffentliche Zeichenfolge Name {get; einstellen; } öffentliche List Bücher {bekommen; einstellen; } }

In der Book Klasse bevölke ich auch im Konstruktor. Als Drall, habe ich das Buch Eigenschaft jedes Author zu 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; } 
    } 

Der Code würde dann so etwas wie:

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; 

    } 

Jede wie dieses erstellt Buch von LINQ-Abfragen ausgewählt werden würde, oder wie auch immer du es machen willst. Außerdem wäre die Kette unendlich. In diesem Fall kann ich den Titel auswählen. Von:

string bookTitle = mobyDick.Name; 

Aber ich kann es auch auf einem anderen Niveau ziehen wie:

string bookTitle = mobyDick.Authors[0].Books[0].Authors[0].Books[0].Authors[0].Books[0]; 

In diesem Fall wird nur ein Buch mit von einem Autor geschrieben, wird das Ergebnis das gleiche sein.

Im folgenden Beispiel. Ich erstelle eine Bibliothek mit zwei Büchern. Und dann suche ich nach Büchern von einem Autor.

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