Die Community zu .NET und Classic VB.
Menü

Tipp-Upload: VB.NET 0303: LinqToSQL-DataContext

 von 

Über den Tipp  

Dieser Tippvorschlag ist noch unbewertet.

Der Vorschlag ist in den folgenden Kategorien zu finden:

  • Datenbanken und XML

Dem Tippvorschlag wurden folgende Schlüsselwörter zugeordnet:
LinqToSQL, DataContext, Dataset

Der Vorschlag wurde erstellt am: 21.08.2008 02:03.
Die letzte Aktualisierung erfolgte am 11.01.2009 12:34.

Zurück zur Übersicht

Beschreibung  

Die LinqToSQL - Klasse (DataContext, Dbml) ist der Nachfolger des bisherigen typisierten Datasets. Es beinhaltet einen OR-Mapper, bei dem man die Datenklassen in einem besseren Designer als dem Dataset-Designer designen kann.
Der generierte Code der Datenklassen ist wesentlich eleganter, vermutlich auch performanter, v.a. aber leserlicher als die bisherigen, in die "XYDataset.Designer.vb" generierten Klassen.
Ein "lazy loading" (Nachladen von Daten erst, wenn sie gebraucht werden) ist voreingestellt.
Die Umständlichkeit, mit mehreren TableAdaptern zu hantieren, entfällt - der Datacontext wird als Einheit abgespeichert.
Interessant die Option, sich die generierten SQL-Commands ausgeben zu lassen.
Besonders angenehm (und das wesentliche an diesem Tipp):
Mit dem Befehl .CreateDatabase() kann ein Datacontext eine SQLServer-Datenbank neu generieren, passend zu den im Dbml-Designer erstellten Datenklassen. Die Arbeit im total unübersichtlichen "Tabellen-Designer" des Datenbank-Explorers kann also durch den komfortablen Dbml-Designer ersetzt werden.

3 (sehr wehe) Wehmutstropfen:
- Der DataContext unterstützt ausschließlich den SQL-Server. Das Dataset bestand unabhängig von jeder Datenbank. Für "kleine" Einheiten (bis 5MB) konnte man u.U. performanter jeweils komplett von der Festplatte laden/speichern, anstatt einen Datenbank-Provider zu bemühen. Diese Option fällt derzeit weg.
- Im Dbml-Designer gibt es keine Möglichkeit, bei der zu generierenden Datenbank eine Löschweitergabe für verknüpfte Tabellen zu designen. Man muß im generierten Code alle vorgefundenen Association-Attribute mit dem zusätzlichen optionalen Paramater DeleteRule:="Cascade" nachbessern. Diese Nachbesserung muß nach jedem Neu-Generieren der Dbml erneut erfolgen.
- Der OR-Mapper generiert für Löschungen untergeordneter Datensätze kein DELETE-Command, sondern ein UPDATE, das den Foreign-Key auf DBNull setzt. Dieses Verhalten kann die hier vorgestellte Klasse "DataContextBase" korrigieren, die im Dbml-Designer als Base-Class anzugeben ist.

Schwierigkeitsgrad

Schwierigkeitsgrad 3

Verwendete API-Aufrufe:

Download:

Download des Beispielprojektes [21,93 KB]

' Dieser Source stammt von http://www.activevb.de
' und kann frei verwendet werden. Für eventuelle Schäden
' wird nicht gehaftet.

' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum.
' Ansonsten viel Spaß und Erfolg mit diesem Source!
'
' Beachten Sie, das vom Designer generierter Code hier ausgeblendet wird.
' In den Zip-Dateien ist er jedoch zu finden.

' ------------ Anfang Projektgruppe CreateMdf.sln ------------
' ----------- Anfang Projektdatei CreateMdf.vbproj -----------
' ------------- Anfang Datei DataContextBase.vb  -------------
' IDE-Voreinstellungen:
' Option Strict On
' Option Explicit On
' Option Infer On

' Projekt-Voreinstellungen
' Imports System
' Imports System.Drawing
' Imports System.Windows.Forms
' Imports System.Collections.Generic
' Imports System.Linq

Imports System.Reflection
Imports System.Data.Linq
Imports System.Data.Linq.Mapping

Public MustInherit Class DataContextBase

    Inherits DataContext

    Protected Sub New(ByVal connection As System.Data.IDbConnection, ByVal mappingSource As _
        MappingSource)

        ' diese eigentlich nutzlose New-Überladung ist erforderlich, da der Dbml-Designer
        ' Code generiert, der darauf zugreift
        MyBase.New(connection)
        Throw New NotSupportedException

    End Sub

    Protected Sub New(ByVal connection As String, ByVal mappingSource As MappingSource)

        MyBase.New(connection, mappingSource)

    End Sub

    Public Overrides Sub SubmitChanges(ByVal failureMode As ConflictMode)

        For Each Entity In MyBase.GetChangeSet.Updates

            ' Ist bei einer Entity ein ForeignKey auf Null gesetzt, so ist diese Entity zu
            ' löschen statt zu updaten
            Dim tpU = Entity.GetType
            Dim Tb = MyBase.GetTable(tpU)
            Dim E = Entity

            Dim F = From Association In MyBase.Mapping.GetMetaType(tpU).Associations Where _
                Association.IsForeignKey AndAlso DirectCast(Association.ThisMember.Member, _
                PropertyInfo).GetValue(E, Nothing) Is Nothing

            If F.Any() Then
                Tb.DeleteOnSubmit(E)

                Exit For

            End If

        Next

        MyBase.SubmitChanges(failureMode)

    End Sub

End Class

' -------------- Ende Datei DataContextBase.vb  --------------
' --------------- Anfang Datei frmCreateMdf.vb ---------------
Imports System.IO
Imports System.Reflection

Public Class frmCreateMdf

    ' zum Databinding: im Datenfenster wurde diesem Projekt eine Objekt-DataSource
    ' hinzugefügt, erzeugt aus der Klasse CreateMdf.Category (dem übergeordneten Datenobjekt
    ' des Dbml-Designers)
    ' das Category-Item wurde aus dem Datenfenster auf das linke DataGridView gezogen, das
    ' im Category-Item enthaltene Articles-Item auf das rechte Grid.

    Private _DBName As String = Path.GetFullPath("DataBase.mdf")
    Private _DB As MdfTemplateDataContext

    Private Sub frmCreateMdf_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
        Handles Me.Load

        ReConnectDB()

    End Sub

    Private Sub ReConnectDB()

        ' Verwerfen und neu erstellen des DataContextes stellt den Zustand vor dem letzten
        ' .SubmitChanges() wieder her.
        If _DB IsNot Nothing Then _DB.Dispose()
        _DB = New MdfTemplateDataContext(_DBName)
        _DB.Log = Console.Out
        Me.CategoryBindingSource.DataSource = _DB.Categories

    End Sub

    Private Sub RecreateDB()

        If _DB.DatabaseExists Then

            ' _DB.CreateDatabase() bewirkt auch einen Eintrag bei der SQL-Server-Instanz des
            ' Computers. Daher muß vor Neu-Erstellung einer schon vorhandenen .mdf die
            ' vorherige Version mit DeleteDatabase() entfernt und ausgetragen werden.
            _DB.DeleteDatabase()
        End If

        _DB.Dispose()
        _DB = New MdfTemplateDataContext(_DBName)
        _DB.Log = Console.Out
        _DB.CreateDatabase()
        Me.CategoryBindingSource.DataSource = _DB.Categories

    End Sub

    Private Sub MenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles ReCreateToolStripMenuItem.Click, ReConnectToolStripMenuItem.Click, _
        SaveToolStripMenuItem.Click, GenerateEntriesToolStripMenuItem.Click

        Select Case True

            Case sender Is ReCreateToolStripMenuItem
                RecreateDB()

            Case sender Is ReConnectToolStripMenuItem
                ReConnectDB()

            Case sender Is GenerateEntriesToolStripMenuItem

                Dim Rnd As New Random(Environment.TickCount)

                Static ID As Integer

                For I = 0 To 1
                    ID += 1

                    Dim Cat As New Category() With {.Name = "Category" & ID}

                    For J = 0 To 2
                        ID += 1

                        Dim ArtName = Cat.Name & "Article" & ID

                        Dim Art = New Article() With {.Name = ArtName, .Price = Rnd.Next(0, _
                            10000) / 100}

                        Cat.Articles.Add(Art)
                    Next

                    CategoryBindingSource.List.Add(Cat)
                Next

            Case sender Is SaveToolStripMenuItem
                _DB.SubmitChanges()

        End Select

    End Sub

    Private Sub frmCreateMdf_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) _
        Handles Me.Disposed

        _DB.Dispose()

    End Sub

End Class

' ---------------- Ende Datei frmCreateMdf.vb ----------------
' ------------ Ende Projektdatei CreateMdf.vbproj ------------
' ------------- Ende Projektgruppe CreateMdf.sln -------------

	

Diskussion  

Diese Funktion ermöglicht es, Fragen, die die Veröffentlichung des Tipps betreffen, zu klären, oder Anregungen und Verbesserungsvorschläge einzubringen. Nach der Veröffentlichung des Tipps werden diese Beiträge nicht weiter verlinkt. Allgemeine Fragen zum Inhalt sollten daher hier nicht geklärt werden.

Um eine Diskussion eröffnen zu können, müssen sie angemeldet sein.