Rainer's profileCyrons BlogPhotosBlogListsMore Tools Help

Blog


    February 12

    LINQ to SQL Insert mit CrossTable

    LINQ2SQL bietet elegante Möglichkeiten für den Umgang mit einer SQL-Datenbank. Um die Verknüpfung von primary- und foreign-keys braucht man sich laut MSDN nicht mehr zu kümmern. Zur Zeit mache ich intensive Übungen auf dem Gebiet und arbeite dafür mit verschieden gestrickten Test-Datenbanken. Eine davon möchte ich hier vorstellen. Der Grund: Ich habe viel Zeit mit der Suche nach Informationen bezüglich Inserts mit Crosstables verbracht, war über die vorgestellten Lösungen aber nicht zufrieden. Immer wieder sah ich Beispiele, in denen eine Hälfte des Datensatzes schon existierte, und die andere über eine Referenz darauf angelegt und über die Crosstable verlinkt wurde. In der Regel geschah das immer über die Extension-Methode Single. Siehe hierzu das Tutorial von Scott Guthrie:

    http://weblogs.asp.net/scottgu/archive/2007/07/11/linq-to-sql-part-4-updating-our-database.aspx

    Ich suchte aber nach einer anderen Möglichkeit. Für die Demonstration hier zuerst die kleine Testdatenbank:

    image

     

    Es geht darum, in einem Rutsch einen neuen Autor mit einem neuen Buch anzulegen - und zwar ohne die IDs quasi händisch in die Crosstable zu insertieren! Hier ist meine Lösung:

          private void AddNewAuthorAndNewBook()
          {
             TestDbDataContext testDb = new TestDbDataContext();
             BookAuthor bookAuthor = new BookAuthor();
             bookAuthor.ID = Guid.NewGuid();
             Author author = new Author
             {
                ID = Guid.NewGuid(),
                AuthorName = "Testautor",
                Residence = "Teststadt"
             };
             Book book = new Book
             {
                ID = Guid.NewGuid(),
                BookName = "Testbuch",
                Price = 1.95m
             };
                      
             bookAuthor.Author = author;
             bookAuthor.Book = book;         
             testDb.BookAuthors.InsertOnSubmit(bookAuthor);         
             testDb.SubmitChanges();         
          }

    Das ist natürlich nur die Grundlage. Die Methode prüft vor dem Insert nicht, ob der Datensatz evtl. schon vorhanden ist. Ich habe das der Übersichtlichkeit halber nicht implementiert. Interessant an diesem Verfahren ist, daß die neuen Datensätze nicht, wie man zuerst denken mag, über die entsprechenden Tabellenklassen (Author und Book) des Mappers eingesetzt werden, sondern explizit über eine Instanz der Crosstable-Klasse (bookAuthor)!

    February 09

    Bier holen, OOP Version

    Früher war alles so einfach:
    10 GOTO Kühlschrank
    20 GET Beer
    30 IF Beer = 0 THEN BREAK

    Heute ist die Zeit der objektorientierten Programmierung (OOP). Das ermöglicht es, neues Bier zu kaufen. Für OOP müssen wir aber erst einmal das System aufbröseln:
    Bier ist ein Objekt mit Eigenschaften (Werten), aber ohne direkte Funktionalität. Damit ist es prädestiniert für ein struct.
    Der Kühlschrank (Fridge) hat nicht nur Eigenschaften, sondern auch Funktionen. Somit wird er als Klasse erstellt.
    Der Biereinkauf (Buy.GetBeer(amount)) ist ein komplexes System und verdient eine eigene Assembly mit eigenem Namensraum (Shop).

    using System;
    using System.Collections.Generic;
    
    namespace BeerOOP
    {
       class Program
       {
          BeerBottle beerBottle;
          Fridge myFridge;
    
          public Program()
          {
             beerBottle = new BeerBottle();
             myFridge = new Fridge();
          }
    
          static void Main()
          {
             int intoxicationLevel = 0;
             Program that = new Program();
             while(intoxicationLevel < 15)
             {
                if(that.myFridge.BeerContent.Count == 0)
                {
                   if(intoxicationLevel < 10)
                   {
                      int amount = 6;
                      BeerBottle[] myBeer =
                         new BeerBottle[(int)Shop.Buy.GetBeer(amount)];
                      that.myFridge.BeerContent.AddRange(myBeer);
                      that.beerBottle.Beer = 1;
                      intoxicationLevel = that.DrinkBeer(intoxicationLevel);
                   }
                   else
                      throw new Exception("Zu besoffen um Bier zu kaufen!");
                }
                else
                   intoxicationLevel = that.DrinkBeer(intoxicationLevel);
             }
    } private int DrinkBeer(int intoxicationLevel) { beerBottle.Beer = 0; if(beerBottle.IsEmpty) myFridge.BeerContent.RemoveAt(myFridge.BeerContent.Count - 1); return intoxicationLevel + 1; } } public struct BeerBottle { public object Beer { get; set; } public bool IsEmpty { get { if((int)Beer == 0) return true; else return false; } } } public class Fridge { // Mehr als zwei Sixpacks passen nicht rein. List<BeerBottle> beerContent = new List<BeerBottle>(12); public List<BeerBottle> BeerContent { get { return beerContent; } set { beerContent = value; } } } }