Announcement

Collapse
No announcement yet.

Relations und Constrains

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Relations und Constrains

    Hallo,

    ich habe in einem DataSet zwei Tabellen erzeugt und möchte nun eine 1:n-Beziehung mit Löschweitergabe zwischen diesen beiden anlegen. Über DataSet.Relations habe ich bereits eine Relation angelegt. Damit kann ich auch wunderbar die Funktion DataRow.GetChildRows() nutzen. Problematisch wird die Löschweitergabe, da ich dafür ein Constraint benötge. Füge ich in Table.Constraints einen neuen ForeignKeyConstraint hinzu, kommt die Fehlermeldung beim Start, dass bereits eine Relation besteht.

    Lasse ich die Relation weg, funktioniert der Constraint. Jedoch kann ich nicht mehr mit GetChildRows() arbeiten, da die Relation nicht mehr vorhanden ist.

    Ist ein wenig merkwürdig.

    Danke.

  • #2
    Hallo,

    beim Einrichten einer DataRelation kann man explizit festlegen, ob dabei automatisch auch ein Contraint erzeugt werden soll oder nicht. Das folgende Beispiel demonstriert dies anhand der Northwind-Datenbank des MS SQL Server 2000:
    <pre>
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim sConStr = "data source=P4W2K;initial catalog=Northwind;integrated security=SSPI"
    Dim aCon As New SqlConnection(sConStr)
    aCon.Open()
    Dim aCmd As New SqlCommand("SELECT * FROM Customers", aCon)
    Dim aDA As New SqlDataAdapter(aCmd)
    Dim aDS As New DataSet()
    aDA.Fill(aDS, "Customers")
    aCmd.CommandText = "SELECT * FROM Orders"
    aDA.Fill(aDS, "Orders")
    Dim parentCol As DataColumn
    Dim childCol As DataColumn
    parentCol = aDS.Tables("Customers").Columns("CustomerID")
    childCol = aDS.Tables("Orders").Columns("CustomerID")
    Dim relCustOrder As DataRelation
    relCustOrder = New DataRelation("CustomersOrders", parentCol, childCol, True)
    aDS.Relations.Add(relCustOrder)
    ' Beziehungen anzeigen (siehe VB.NET-Beispiel unter ConstraintCollection Class
    Dim t As DataTable
    For Each t In aDS.Tables
    Debug.WriteLine(t.TableName)
    Debug.WriteLine("Constraints.Count " _
    + t.Constraints.Count.ToString())
    Debug.WriteLine("ParentRelations.Count " _
    + t.ParentRelations.Count.ToString())
    Debug.WriteLine("ChildRelations.Count " _
    + t.ChildRelations.Count.ToString())
    Dim cstrnt As Constraint
    For Each cstrnt In t.Constraints
    Debug.WriteLine(cstrnt.ConstraintName)
    Debug.WriteLine(cstrnt.GetType())
    Next cstrnt
    Next t

    End Sub
    </pre>

    Fall A) relCustOrder = New DataRelation("CustomersOrders", parentCol, childCol, <b>True</b>)

    Die Contraints (ForeignKeyConstraint, UniqueConstraint) werden automatisch angelegt: Debug-Output:
    <pre>
    Customers
    Constraints.Count 1
    ParentRelations.Count 0
    ChildRelations.Count 1
    Constraint1
    System.Data.UniqueConstraint
    Orders
    Constraints.Count 1
    ParentRelations.Count 1
    ChildRelations.Count 0
    CustomersOrders
    System.Data.ForeignKeyConstraint
    </pre>
    Fall B) relCustOrder = New DataRelation("CustomersOrders", parentCol, childCol, <b>False</b>)

    Die Contraints werden nicht automatisch angelegt: Debug-Output:
    <pre>
    Customers
    Constraints.Count 0
    ParentRelations.Count 0
    ChildRelations.Count 1
    Orders
    Constraints.Count 0
    ParentRelations.Count 1
    ChildRelations.Count 0
    </pre>
    Daher sollte der folgende Weg funktionieren (habe das jedoch aus Zeitgründen noch nicht ausprobiert):
    <pre>
    ...
    ' Schritt 1: Zuerst DataReletion ohne Constraint
    Dim relCustOrder As DataRelation
    relCustOrder = New DataRelation("CustomersOrders", parentCol, childCol, False)
    aDS.Relations.Add(relCustOrder)
    ' Schritt 2: Danach ForeignKeyConstraint mit Rule.Cascade
    Dim custOrderFK As ForeignKeyConstraint = New ForeignKeyConstraint("CustOrderFK", _
    aDS.Tables("Customers").Columns("CustomerID"), _
    aDS.Tables("Orders").Columns("CustomerID"))
    custOrderFK.DeleteRule = Rule.Cascade
    aDS.Tables("Orders").Constraints.Add(custOrderFK)
    ...
    </pre>
    &#10

    Comment


    • #3
      Hallo
      wer kann helfen einfache Relations funktionieren. Wie funktionieren mehrfache.

      Verschiedene Reihen aus einer Tabelle zu mehreren Tabellen in Bezeihung stellen. Sämtliche Controls sind lee

      Comment


      • #4
        Hallo,

        da gibt es keinen Unterschied. Das folgende Beispiel demonstriert dies mit neu angelegten Tabellen in der MS SQL Server 2000-Datenbank <i>tempdb</i>:

        a) Datenbank
        <pre>
        USE tempdb
        GO

        CREATE TABLE ANR (
        ANRID INTEGER NOT NULL IDENTITY PRIMARY KEY,
        Anrede VARCHAR(30) NOT NULL)
        GO

        INSERT INTO ANR (Anrede) VALUES ('Herr')
        INSERT INTO ANR (Anrede) VALUES ('Frau')
        INSERT INTO ANR (Anrede) VALUES ('Firma')
        INSERT INTO ANR (Anrede) VALUES ('')
        GO

        CREATE TABLE KDN (
        KNDID INTEGER NOT NULL IDENTITY PRIMARY KEY,
        ANRID INTEGER NOT NULL REFERENCES ANR(ANRID),
        Name1 VARCHAR(35) NOT NULL,
        Name2 VARCHAR(35),
        Datum DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP)
        GO

        INSERT INTO KDN (ANRID,Name1,Name2) VALUES (3,'Manfred Mustermann','Malermeister')
        GO

        CREATE TABLE TEL (
        TELID INTEGER NOT NULL IDENTITY PRIMARY KEY,
        Typ VARCHAR(10) NOT NULL)
        GO

        INSERT INTO TEL (Typ) VALUES ('Festnetz')
        INSERT INTO TEL (Typ) VALUES ('Handy')
        INSERT INTO TEL (Typ) VALUES ('FAX')
        GO

        CREATE TABLE KDNTEL (
        KDNTELID INTEGER NOT NULL IDENTITY PRIMARY KEY,
        KDNID INTEGER NOT NULL REFERENCES KDN(KNDID),
        TELID INTEGER NOT NULL REFERENCES TEL(TELID),
        Nummer VARCHAR(14) NOT NULL)
        GO

        INSERT INTO KDNTEL (KDNID,TELID,Nummer) VALUES (1,1,'(036258)51212')
        INSERT INTO KDNTEL (KDNID,TELID,Nummer) VALUES (1,2,'0171/121212')
        GO
        </pre>
        b) Zugriff im Programm (keine visuelle XSD-Konfiguration, sondern alles via Code):
        <pre>
        Private Sub Form2_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.SqlDataAdapter1.Fill(Me.DataSetKomplex21)
        Me.SqlDataAdapter2.Fill(Me.DataSetKomplex21)
        Me.SqlDataAdapter3.Fill(Me.DataSetKomplex21)
        Me.SqlDataAdapter4.Fill(Me.DataSetKomplex21)
        StatusBar1.Text = "DataSet wurde gefüllt."
        End Sub

        Private Sub ButtonCheck_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonCheck.Click
        Dim aDT As DataTable
        Dim aNodeParent, aNodeContraint As TreeNode
        TreeView1.Nodes.Clear()
        For Each aDT In DataSetKomplex21.Tables
        aNodeParent = TreeView1.Nodes.Add(aDT.TableName)
        aNodeParent.Nodes.Add("Constraints.Count " _
        + aDT.Constraints.Count.ToString())
        aNodeParent.Nodes.Add("ParentRelations.Count " _
        + aDT.ParentRelations.Count.ToString())
        aNodeParent.Nodes.Add("ChildRelations.Count " _
        + aDT.ChildRelations.Count.ToString())
        aNodeContraint = aNodeParent.Nodes.Add("Constraints")
        Dim aCstrn As Constraint
        For Each aCstrn In aDT.Constraints
        aNodeContraint.Nodes.Add(aCstrn.ConstraintName)
        aNodeContraint.Nodes.Add(aCstrn.GetType().ToString )
        Next aCstrn
        Next aDT
        StatusBar1.Text = "DataSet wurde untersucht."
        End Sub

        Private Sub ButtonCheckRelations_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonCheckRelations.Click
        Dim aDR As DataRelation
        Dim aNodeParent, aNodeContraint As TreeNode
        TreeView2.Nodes.Clear()
        For Each aDR In DataSetKomplex21.Relations
        aNodeParent = TreeView2.Nodes.Add(aDR.RelationName)
        Next aDR
        StatusBar1.Text = "DataSet-Kollektion Relations wurde untersucht: " + _
        DataSetKomplex21.Relations.Count.ToString()
        End Sub

        Private Sub ButtonRelations_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonRelations.Click
        Dim aRel As DataRelation
        ' Beziehung zwischen ANR -> KDN
        aRel = New DataRelation("ANR_KDN", _
        DataSetKomplex21.Tables("ANR").Columns("ANRID"), _
        DataSetKomplex21.Tables("KDN").Columns("ANRID"), True)
        DataSetKomplex21.Relations.Add(aRel)
        ' Beziehung zwischen KDN -> KDNTEL
        aRel = New DataRelation("KDN_KDNTEL", _
        DataSetKomplex21.Tables("KDN").Columns("KNDID"), _
        DataSetKomplex21.Tables("KDNTEL").Columns("KDNID") , True)
        DataSetKomplex21.Relations.Add(aRel)
        ' Beziehung zwischen TEL -> KDNTEL
        aRel = New DataRelation("TEL_KDNTEL", _
        DataSetKomplex21.Tables("TEL").Columns("TELID"), _
        DataSetKomplex21.Tables("KDNTEL").Columns("TELID") , True)
        DataSetKomplex21.Relations.Add(aRel)
        End Sub
        </pre>
        Die beiden Prüfmethoden stellen das Ergebnis visuell in einem TreeView dar, so dass man sich vom Vorhandensein der Contraints zwischen den einzelnen Tabellen auch visuell überzeugen kann.

        Beim Data Binding für das DataGrid muss man nur beachten, dass sowohl <b>DataSource</b> als auch <b>DataMember</b> korrekt gesetzt werden: <br>
        a) DataSource = DataSet <br>
        b) DataMember = Relation (Beispiel: KDN.KDN_KDNTEL)
        &#10

        Comment

        Working...
        X