Benutzer mit den meisten Antworten
[VB.NET 2005 Prof] Performanceprobleme bei Datenbankanwendung (SQL Server 2005/2008)

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
Antworten
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 ComboBoxPrivate mDT As DataTable
Private mDV1 As DataView
Private mDV2 As DataView
Private mDV3 As DataViewPrivate Sub Form1_Load _
(ByVal sender As System.Object, _
ByVal e As System.EventArgs _
) Handles MyBase.LoadCreateData()
CreateControls()
End SubPrivate Sub CreateControls()
Dim Fnt As New Font("Arial", 12)
Combo1 = New ComboBox
Combo2 = New ComboBox
Combo3 = New ComboBoxWith 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 WithmDV1 = New DataView(mDT)
mDV2 = New DataView(mDT)
mDV3 = New DataView(mDT)End Sub
End ClassProgramm 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) -
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 DataViewPrivate 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 ComboBoxPrivate Sub Form1_Load _
(ByVal sender As System.Object, _
ByVal e As System.EventArgs _
) Handles MyBase.LoadCreateData()
CreateControls()
Combo1.DataSource = mBS1
Combo1.DisplayMember = mDT.Columns(1).ColumnNameCombo2.DataSource = mBS2
Combo2.DisplayMember = mDT.Columns(1).ColumnNameCombo3.DataSource = mBS3
Combo3.DisplayMember = mDT.Columns(1).ColumnNameDGV.DataSource = mDV0
With DGV
.DataSource = mDV0
.Columns(0).DefaultCellStyle.Alignment = _
DataGridViewContentAlignment.MiddleRight.Columns(3).DefaultCellStyle.Alignment = _
DataGridViewContentAlignment.MiddleRight.AutoResizeColumns()
End With
'Stop
End SubPrivate 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.BottomEnd With
Me.Controls.Add(DGV)End Sub
Private Sub CreateData()
Dim i As Integer
Dim DR As DataRowmDT = 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 WithmDV0 = New DataView(mDT)
mDV1 = New DataView(mDT)
mDV2 = New DataView(mDT)
mdV3 = New DataView(mDT)mBS1 = New BindingSource
mBS1.DataSource = mDTmBS2 = New BindingSource
mBS2.DataSource = mDTmBS3 = New BindingSource
mBS3.DataSource = mDTEnd Sub
End ClassGruß aus St.Georgen
Peter Götz
www.gssg.de (mit VB-Tipps u. Beispielprogrammen) -
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.
-
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) -
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