none
[VB.NET 2005 Prof] Performanceprobleme bei Datenbankanwendung (SQL Server 2005/2008) RRS feed

  • Frage

  • Guten Morgen Community,

    habe ein größeres Problem bei der Entwicklung meiner Anwendung. Ich benutze Visual Studio 2005 Prof in Verbindung mit einem SQL Server 2005. Ich bin dabei eine Software für Produktstammverwaltung etc. zu entwerfen. Den Größtenteil mache über den Designer, allerdings bin ich jetzt auf ein störendes Problem gestoßen. Z.B. habe ich ein Windows Form indem es mehrere Comboboxen gibt. Der Inhalt dieser ist jeweils mit einem Datenbanktabellenfeld verknüpft (selbe Tabelle z.b. Tabelle: tbl_stammdaten$produktxx Felder: BN1,BN2,etc...). Zur Auswahl habe ich nun für alle ca. 5-10 Comboboxen ein und die selbe Tabelle&Feld als Quelle angegeben. Damit alle Werte in den Comboxen auch einzelnd ausgewählt werden können, muss ich bei den Comboboxen jeweils die Tabelle&Feld auswählen damit eine neue BindingSource generiert wird. Wenn die Felder über ein und die selbe BindingSource laufen, werden logischeweise bei einer Auswahl die andern Felder direkt mit ausgewählt. Jetzt habe ich ein Windows Form mit 12 Comboboxen und natürlich dementsprechend 12 BindingSources, aber wenn ich dieses Form nun ausführe muss ich 5-6sek. warten bis es aufgeht. Ist das normal? Gibt es eine bessere Lösung die für einen Einsteiger umsetzbar ist :D? Sobald ich die BindingSources entferne öffnet sich dies natürlich wieder direkt.

     

    MfG

    Zidane1x

     

     

    Mittwoch, 21. Juli 2010 09:21

Antworten

  • Ich habe jetzt eine andere Methode verwendet um meine Forms schneller offen zu bekommen, von daher ist dieses Thema erledigt.
    • Als Antwort markiert Zidane1x Donnerstag, 21. Oktober 2010 13:41
    Donnerstag, 21. Oktober 2010 13:41

Alle Antworten

  • Hallo,

    für Deine verschiedenen ComboBoxen brauchst Du nur
    eine einzige DataTable als Datenquelle und lediglich eine
    eigene DataView für jede Deiner Comboboxen.

    Das nachfolgende Beispiel, das Du einfach in ein leeres
    Formmodul (Form1.vb) kopierst, zeigt Dir wie das geht.

    Public Class Form1
        Private WithEvents Combo1 As ComboBox
        Private WithEvents Combo2 As ComboBox
        Private WithEvents Combo3 As ComboBox

        Private mDT As DataTable
        Private mDV1 As DataView
        Private mDV2 As DataView
        Private mDV3 As DataView

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

            CreateData()
            CreateControls()
        End Sub

        Private Sub CreateControls()
            Dim Fnt As New Font("Arial", 12)
            Combo1 = New ComboBox
            Combo2 = New ComboBox
            Combo3 = New ComboBox

            With Combo1
                .Font = Fnt
                .Name = "Combo1"
                .SetBounds(10, 10, 100, .Height)
                .DataSource = mDV1
                .DisplayMember = mDT.Columns(1).ColumnName
            End With
            Me.Controls.Add(Combo1)

            With Combo2
                .Font = Fnt
                .Name = "Combo3"
                .SetBounds(Combo1.Right + 10, 10, 100, .Height)
                .DataSource = mDV2
                .DisplayMember = mDT.Columns(1).ColumnName
            End With
            Me.Controls.Add(Combo2)

            With Combo3
                .Font = Fnt
                .Name = "Combo3"
                .SetBounds(Combo2.Right + 10, 10, 100, .Height)
                .DataSource = mDV3
                .DisplayMember = mDT.Columns(1).ColumnName
            End With
            Me.Controls.Add(Combo3)

        End Sub

        Private Sub CreateData()
            Dim i As Integer
            Dim DR As DataRow
            Dim Values() As String
            Values = New String() {"Hund", "Katze", "Maus", "Elefant", "Tiger"}


            mDT = New DataTable
            With mDT
                .Columns.Add("ID", GetType(Integer))
                .Columns.Add("Text", GetType(String))

                For i = 0 To Values.GetUpperBound(0)
                    DR = .NewRow
                    DR.Item(0) = i
                    DR.Item(1) = Values(i)

                    .Rows.Add(DR)
                Next
            End With

            mDV1 = New DataView(mDT)
            mDV2 = New DataView(mDT)
            mDV3 = New DataView(mDT)

        End Sub
    End Class

    Programm starten und dann kannst Du in jeder der
    drei Comboboxen einen von den anderen ComboBoxen
    unabhängigen Eintrag auswählen.

    Gruß aus St.Georgen
    Peter Götz
    www.gssg.de (mit VB-Tipps u. Beispielprogrammen)

    Mittwoch, 21. Juli 2010 12:09
  • Erstmal danke für die Schnelle Antwort. Liegt das Problem den an einem Fehler den ich mache oder Gibt es allgemein Probleme bei Verwendung von mehreren Bindingsources ( Je eine als Datenquelle der Auswahl der Combobox)?
    Mittwoch, 21. Juli 2010 13:52
  • Hallo,

    da ich Deinen konkreten Code nicht kenne, kann ich nicht
    beurteilen, woher Deine 5 - 6 Sekunden Wartezeit kommen.
    Aus dem selben Grund kann ich auch nicht beurteilen, ob
    und falls ja, welchen Fehler es in Deinem Code gibt.

    Wenn Du auf Deiner Form 12 ComboBoxen mit je einer
    eigenen BindingSource hast, lädtst Du halt einiges an
    unnötigem Ballast in Deinen Speicher. Eine BindingSource
    liefert Dir neben der für Deine ComboBoxen notwendigen
    DataView (BindingSource.List) auch noch eine Menge anderer
    Objekte (z.B. CurrencyManager), Methoden und Eigenschaften
    die Du eigentlich nicht benötigst. Du musst nur mal die
    Member-Liste von BindingSource und DataView
    vergleichen um zu sehen, dass Du mit einer DataView schon
    etwas weniger an Ressource verbrätst. Mal abgesehen von
    div. Eigenschaften u. Methoden ist eine DataView eine simple
    Liste von Zeigern auf bestimmte Datensätze der zugehörigen
    DataTable.

    Das Erstellen von 5 oder auch 12 DataViews zu einer DataTable
    bedeutet normalerweise eine für den Benutzer kaum feststellbare
    Wartezeit. Aber auch das Erstellen einer entspr. Anzahl von
    BindingSources dürfte nicht sehr viel länger dauern.
    Ich vermute aber mal, dass Deine Verzögerung von 5 - 6
    Sekunden eher beim Laden der Daten aus Deiner Datenbank
    entstehen. Aber wie schon erwähnt, kann man ohne Kenntnis
    Deines konkreten Codes nur spekulieren.

    Hier noch ein weiteres Beispiel, mit dem Du die Arbeitsweise mit
    BindingSources und/oder DataViews vergleichen kannst und
    bei dem Du auch siehst, dass Du übersichtlicheren Code erhältst,
    wenn Du Deine DataObjekte via eigenem Code anstatt mit dem
    Designer erstellst. Das Beispiel kannst Du einfach in ein leeres
    Formmodul (Form1.vb) kopieren und dann ablaufen lassen.

    Public Class Form1
        Private mDT As DataTable
        Private mDV1 As DataView
        Private mDV2 As DataView
        Private mDV3 As DataView
        Private mDV0 As DataView

        Private WithEvents mBS1 As BindingSource
        Private WithEvents mBS2 As BindingSource
        Private WithEvents mBS3 As BindingSource
        Private WithEvents DGV As DataGridView
        Private Combo1 As ComboBox
        Private Combo2 As ComboBox
        Private Combo3 As ComboBox

     

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

            CreateData()

            CreateControls()

            Combo1.DataSource = mBS1
            Combo1.DisplayMember = mDT.Columns(1).ColumnName

            Combo2.DataSource = mBS2
            Combo2.DisplayMember = mDT.Columns(1).ColumnName

            Combo3.DataSource = mBS3
            Combo3.DisplayMember = mDT.Columns(1).ColumnName

            DGV.DataSource = mDV0

            With DGV
                .DataSource = mDV0
                .Columns(0).DefaultCellStyle.Alignment = _
                        DataGridViewContentAlignment.MiddleRight

                .Columns(3).DefaultCellStyle.Alignment = _
                        DataGridViewContentAlignment.MiddleRight

                .AutoResizeColumns()
            End With
            'Stop


        End Sub

        Private Sub CreateControls()
            Combo1 = New ComboBox
            With Combo1
                .Name = "Combo1"
                .Font = New Font("Arial", 10)
                .SetBounds(10, 10, 120, .Height)
            End With
            Me.Controls.Add(Combo1)

            Combo2 = New ComboBox
            With Combo2
                .Name = "Combo2"
                .Font = Combo1.Font
                .SetBounds(Combo1.Right + 10, 10, 120, .Height)
            End With
            Me.Controls.Add(Combo2)

            Combo3 = New ComboBox
            With Combo3
                .Name = "Combo3"
                .Font = Combo1.Font
                .SetBounds(Combo2.Right + 10, 10, 120, .Height)
            End With
            Me.Controls.Add(Combo3)

            Me.ClientSize = New Size(Combo3.Right + 10, 400)

            DGV = New DataGridView
            With DGV
                .DefaultCellStyle.Font = _
                        New Font("Aria", 12)

                .ColumnHeadersDefaultCellStyle.Font = _
                        New Font("Arial", 8, FontStyle.Bold)

                .SetBounds _
                        (10, Combo1.Bottom + 20, _
                         Me.ClientSize.Width - 20, _
                         Me.ClientSize.Height - (Combo1.Bottom + 20))

                .Anchor = _
                        AnchorStyles.Left Or _
                        AnchorStyles.Top Or _
                        AnchorStyles.Right Or _
                        AnchorStyles.Bottom

            End With
            Me.Controls.Add(DGV)

        End Sub

        Private Sub CreateData()
            Dim i As Integer
            Dim DR As DataRow

            mDT = New DataTable
            With mDT
                .TableName = "mDT"
                .Columns.Add("ID", GetType(Integer))
                .Columns.Add("LText", GetType(String))
                .Columns.Add("SText", GetType(String))
                .Columns.Add("NumDays", GetType(Integer))

                For i = 1 To 12
                    DR = .NewRow
                    DR.Item(0) = i
                    DR.Item(1) = MonthName(i, False)
                    DR.Item(2) = MonthName(i, True)
                    DR.Item(3) = Date.DaysInMonth(Now.Year, i)
                    .Rows.Add(DR)
                Next
                .AcceptChanges()
            End With

            mDV0 = New DataView(mDT)
            mDV1 = New DataView(mDT)
            mDV2 = New DataView(mDT)
            mdV3 = New DataView(mDT)

            mBS1 = New BindingSource
            mBS1.DataSource = mDT

            mBS2 = New BindingSource
            mBS2.DataSource = mDT

            mBS3 = New BindingSource
            mBS3.DataSource = mDT

        End Sub
    End Class

    Gruß aus St.Georgen
    Peter Götz
    www.gssg.de (mit VB-Tipps u. Beispielprogrammen)

    Donnerstag, 22. Juli 2010 07:34
  • Ok habe jetzt beide Varianten verglichen und konnte nur ein sehr geringen LAdezeitenunterschied feststellen. Inzwischen glaube ich auch das die Datenbanktabelle schuld ist. Das Problem ist diese Auswahltabelle hat 5000 Datensätze ich habe mal 4000 gelöscht und schon ging es fast sofort auf.

     

    Meine Frage jetzt, gibt es da auch noch eine Verbesserung? Evtl. Eine Tabellenansicht mit nur mit der benötigten Spalte? Oder Fragt er sowie die ganzen Spalten der Tabelle ab und braucht genau so lang? Zudem habe ich auch meisten nvarchar Felder verwenden, bin mir nicht sicher ob die Feldwahl auch hierbei eine große Rolle spielt.

    Freitag, 23. Juli 2010 07:52
  • Hallo,

    Ok habe jetzt beide Varianten verglichen und konnte nur ein sehr
    geringen LAdezeitenunterschied feststellen. Inzwischen glaube
    ich auch das die Datenbanktabelle schuld ist. Das Problem ist
    diese Auswahltabelle hat 5000 Datensätze ich habe mal 4000
    gelöscht und schon ging es fast sofort auf.

    Wieviele von diesen 5000 Datensätzen liest Du ein?
    Wie sieht Dein konkreter SelectCommand.CommandText aus?

    Meine Frage jetzt, gibt es da auch noch eine Verbesserung?

    Ohne Deinen konkreten SelectCommand zu kennen, kann ich dazu
    wenig sagen.

    Evtl. Eine Tabellenansicht mit nur mit der benötigten Spalte?
    Oder Fragt er sowie die ganzen Spalten der Tabelle ab und
    braucht genau so lang?

    Nur ein Feld eines Datensatzes bedeutet gegenüber vielen
    Feldern auf jeden Fall eine geringere zu übertragende Datenmenge.
    Noch wichtiger aber wäre es zu wissen, nach welchen Kriterien
    Du wieviele Datensätze aus Deiner zugrundeliegenden DB-Tabelle
    herausliest (SelectCommand.CommandText?).

    Zudem habe ich auch meisten nvarchar Felder verwenden, bin
    mir nicht sicher ob die Feldwahl auch hierbei eine große Rolle spielt.

    s.oben:
    Du solltest mal Deinen konkreten CommandText zeigen, dann
    kann man sich ein besseres Bild machen.

    Gruß aus St.Georgen
    Peter Götz
    www.gssg.de (mit VB-Tipps u. Beispielprogrammen)

    Sonntag, 25. Juli 2010 07:28
  • Ich lese alle 5400 Datensätze ein, da ich das ganze leider nicht exakt eingrenzen kann. Von der Tabelle mit diesen 5400 Datensätzen habe im moment im TableAdapter nur noch 2 Spalten in der Abfrage Nvarchar(15) & Nvarchar(255)

     

     

    Habe mir den CommandText nochmal angesehen(Ist nicht selbst geschrieben habe es über Assistenten und Designer gemacht). Ist etwas unübersichtlich daher vll. lieber die Abfragen

     

    Tabelle mit 5000 Datensätzen:

     

    SELECT
    
    
    
    
    
     BN, MkAlt, Bezeichnung
    FROM
    
    
    
    
    
     [Bestellartikel]
    

     

    Kriterien lohnen sich hier nicht würde auch nicht sehr gerne welche verwenden, da sich dort stetig was ändert.

     

    Hier nochmal auszüge aus der designer.vb die vom Assistenten erzeugt wurden von der SelectCommand.CommandText :

     

    <Global.System.Diagnostics.DebuggerNonUserCodeAttribute()> _
        Private Sub InitCommandCollection()
          Me._commandCollection = New Global.System.Data.SqlClient.SqlCommand(0) {}
          Me._commandCollection(0) = New Global.System.Data.SqlClient.SqlCommand
          Me._commandCollection(0).Connection = Me.Connection
          Me._commandCollection(0).CommandText = "SELECT    BN, MkAlt, Bezeichnung"&Global.Microsoft.VisualBasic.ChrW(13)&Global.Microsoft.VisualBasic.ChrW(10)&"FROM      [Bestella"& _ 
            "rtikel]"
          Me._commandCollection(0).CommandType = Global.System.Data.CommandType.Text
        End Sub

     

     

     

    Montag, 16. August 2010 13:44
  • Ich habe jetzt eine andere Methode verwendet um meine Forms schneller offen zu bekommen, von daher ist dieses Thema erledigt.
    • Als Antwort markiert Zidane1x Donnerstag, 21. Oktober 2010 13:41
    Donnerstag, 21. Oktober 2010 13:41