DataGridView - Erstellte Spalten Dynamisch auf MSSQL DB befüllen

  • VB.NET

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von michach.

    DataGridView - Erstellte Spalten Dynamisch auf MSSQL DB befüllen

    Hallo zusammen,

    ich versuche diverse Werte aus der MSSQL DB abzurufen, dabei gibt es keine fest definierten Spalten, diese Variieren von Abfrage zu Abfrage.
    Bedeutet:

    Rufe ich deine eine Select Statement ab, sollen z.Bsp. Spalten wie: "Benutzer", "Adresse", "Telefonnumer" ausgegeben werden.
    Bei einem anderen Select Statement kommen dann Spalten wie: "ID", "Adresse", "Hausnummer", "PLZ", "Bemerkung".

    Die Ausgabe variiert also in Anzahl und Breite der Spalten.
    Da in der DB die Spaltennamen teilweise mit nicht definierten Namen belegt sind, sollen die Spalten bei der Ausgabe auch umbenannt werden.

    Ich möchte jetzt also abhängig von dem Select Statement, folgendes durchführen.

    - Spalten bekommen einen Expliziten Namen
    - Spalten bekommen eine vordefinierte Breite zugewiesen
    - Spalten werden aus der DB befüllt.

    Folgendes habe ich bisher, was mir die Werte aus der DB auch anzeigt:

    VB.NET-Quellcode

    1. Sub sql_Registrierungen()
    2. Dim Conn As New SqlConnection
    3. Dim da As SqlDataAdapter
    4. Dim dt As New DataTable
    5. Conn.ConnectionString = "Server=xxxxxx,1434;Database=xxxxxx;user id=xxxxxx;password=xxxxxx;"
    6. da = New SqlDataAdapter("select user_binding, mode, device_binding_type, device_binding_data, status, validity_start, validity_end from dbo.enrollment_pass;", Conn)
    7. DataGridView.ColumnCount = 7
    8. DataGridView.Columns(0).Name = "Benutzer"
    9. DataGridView.Columns(1).Name = "Modus"
    10. DataGridView.Columns(1).Name = "Typ"
    11. DataGridView.Columns(1).Name = "Data"
    12. DataGridView.Columns(2).Name = "Status"
    13. DataGridView.Columns(3).Name = "Start"
    14. DataGridView.Columns(4).Name = "Ende"
    15. da.Fill(dt)
    16. DataGridView.DataSource = dt
    17. End Sub


    Wie befülle ich jetzt die von mir mit Namen vordefinierten Spalten mit den Wertern aus der DB und wie kann cih die Breite der Spalten anpassen ?

    Die Spalten werden mit angezeigt, allerdings ohne Werte, zusätzlich wird mir die Ausgabe der DB abgezeigt rechts neben den von mir definierten Spalten, aber mit den Spalten und Werten aus der DB.
    @michach Deine Herangehensweise ist falsch, am DGV machst Du gar nix, das bleibt leer.
    Du erstellst eine DataTable, die Du per TableAdapter mit den Daten der DB befüllst. Nur hier ist was zu tun.
    Dem DGV gibst Du die DataTable als DataSource.
    Feddich.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Dafür gibts keine guten Anleitungen, denn die Idee, beliebige Datensätze von beliebigen Tabellen abzurufen ist schon keine gute Idee.
    Also sicher gibts Anleitungen in diese (ich nenne sie "Datenbrei-") Richtung, aber es ist nicht gut, denen zu folgen.

    Ich kenne jetzt deinen Wissensstand nicht - kannst du Datentypen unterscheiden?
    - beherrschst du Datenmodellierung?
    - kannst du mit Databinding umgehen?

    Wenn eine dieser Fragen auch nur etwas unentschlossen bejaht wird, ists für dich zu früh, eine Datenbank aufzusetzen, und darauf zuzugreifen.
    Da kann nur Murx bei rauskommen.

    Hier mein Plan mit allerlei Anleitungen, wie ich denke, dass man sein Grundlagenwissen schnellstmöglich aufgebaut bekommt: Datenverarbeitungs-Vorraussetzungen
    Dabei gehts nur zum Teil um inhaltliches Wissen, ein großer Teil leitet auch an, zu recherchieren, und mit VisualStudio effizient umzugehen.
    Danke für die Antwort.

    Es sind bestehende Tabellen von einer Anwendung, in unterschiedlichen Tabellen sind Informationen die ich mir über Select Statements raussuche und in eine Tabelle zusammen fasse.
    An der Tabellen Struktur kann ich nichts ändern, die liegt auf eine DB Server und wurde mit der Installation der Anwendung durchgeführt.

    Beispiel:
    In einer Tabelle stehen die User Daten mit userID
    In eine anderen Tabelle die die userID inkl. der Devices die der User in Verwendung hat.
    Eine andere Tabelle hat die userID indkl. einer Gruppen Id in der der User angemeldet ist.
    Wiederum gibt es eine Tabelle mit Gruppen ID und dem Gruppen Namen
    usw.
    usw.
    usw.

    Jenachdem, welche Auswertungen benötigt werden, erfolgen unterschiedliche Select Statements um diese Informationen in einer Tabelle zusammen zu fassen.

    Zum Beispiel wird der User Name inkl. der Software auf dem Device benötigt, in welche Gruppe ist der User, und welchen Softwarestand hat die installierte Softare.
    Alleine dafür rufe ich bestimmt 5 Tabellen mit Select, Join, Where ab um das zusammen in eine Tabelle zu fassen, wobei hier diverse Spalten wiederum nicht benötigt werden aus einzelnen tabellen.

    Mit Listview habe ich das soweit fertig gemacht, und es funktioniert super.
    Anbei das vom ListView:

    VB.NET-Quellcode

    1. Sub sql_Registrierungen()
    2. Dim cmd As New SqlCommand
    3. Dim reader As SqlDataReader
    4. Dim lvitem As ListViewItem
    5. Dim Query As String
    6. Try
    7. sqlConnection1.Open()
    8. Query = "Select user_binding, mode, device_binding_type, device_binding_data, status, validity_start, validity_end from dbo.enrollment_pass;"
    9. cmd = New SqlCommand(Query, sqlConnection1)
    10. reader = cmd.ExecuteReader
    11. Do While reader.Read
    12. ColumnHeader1.Text = "Benutzer"
    13. ColumnHeader1.Width = "200"
    14. lvitem = ListView1.Items.Add(reader("user_binding"))
    15. ColumnHeader2.Text = "Modus"
    16. ColumnHeader2.Width = "100"
    17. lvitem.SubItems.Add(reader("mode"))
    18. ColumnHeader3.Text = "Gerätebindungstyp"
    19. ColumnHeader3.Width = "130"
    20. If reader("device_binding_type") Is DBNull.Value Then
    21. lvitem.SubItems.Add("<NULL>")
    22. Else
    23. lvitem.SubItems.Add(reader("device_binding_type"))
    24. End If
    25. ColumnHeader4.Text = "Gerätebingungsdaten"
    26. ColumnHeader4.Width = "130"
    27. If reader("device_binding_data") Is DBNull.Value Then
    28. lvitem.SubItems.Add("<NULL>")
    29. Else
    30. lvitem.SubItems.Add(reader("device_binding_data"))
    31. End If
    32. ColumnHeader5.Text = "Registrierungsstatus"
    33. ColumnHeader5.Width = "150"
    34. lvitem.UseItemStyleForSubItems = False
    35. If reader("status") = "REDEEMED" Then
    36. lvitem.SubItems.Add(reader("status")).ForeColor = Color.Green
    37. ElseIf reader("status") = "FAILED" Then
    38. lvitem.SubItems.Add(reader("status")).ForeColor = Color.Red
    39. Else
    40. lvitem.SubItems.Add(reader("status")).ForeColor = Color.Orange
    41. End If
    42. ColumnHeader6.Text = "Erstellungszeit"
    43. ColumnHeader6.Width = "130"
    44. lvitem.SubItems.Add(reader("validity_start"))
    45. ColumnHeader7.Text = "Gültig bis"
    46. ColumnHeader7.Width = "130"
    47. lvitem.SubItems.Add(reader("validity_end"))
    48. Loop
    49. lbl_ZeilenErgebnis.Text = ListView1.Items.Count()
    50. reader.Close()
    51. sqlConnection1.Close()
    52. Catch ex As Exception
    53. 'MessageBox.Show(ex.Message)
    54. Finally
    55. sqlConnection1.Dispose()
    56. End Try
    57. End Sub



    Teilweise habe ich Select Abfrage in diese Richtung:

    SQL-Abfrage

    1. sqlConnection1.Open()
    2. Query = "
    3. select id
    4. ,firstname
    5. ,lastname
    6. ,addlattr2
    7. ,max(PRODUCT_NAME) as PRODUCT
    8. ,max(MODEL_ID) as Model
    9. ,os_version
    10. ,Serial_Number
    11. ,MAX(RoleName) as Rolle
    12. ,LAST_AUTH_DATE
    13. ,Activation_Date
    14. from
    15. (
    16. select usr.id, usr.firstname, usr.lastname, usr.addlattr2, ds.os_version, ds.Serial_Number, rl.name as RoleName, du.LAST_AUTH_DATE, enr.Activation_Date, dp.device_id, dp.Name, dp.Value
    17. FROM dbo.users usr
    18. join dbo.Device_User du
    19. on usr.id = du.USER_ID
    20. join dbo.Device_Search ds
    21. on du.device_id = ds.device_id
    22. join dbo.Device_Property dp
    23. on dp.device_id = du.device_id
    24. join userroles ur
    25. on usr.id = ur.userid
    26. join roles rl
    27. on rl.id = ur.roleid
    28. join enrollment enr
    29. on enr.device_id = du.device_id
    30. ) data
    31. pivot (max(value) for name in ([PRODUCT_NAME], [MODEL_ID])) PIV
    32. group by id, firstname, lastname , addlattr2, os_version, Serial_Number, LAST_AUTH_DATE, Activation_Date;
    33. "


    Leider funktioniert es bei DataGridView nicht so einfach wie bei ListView wie es aussieht.
    Ich liebe Kommunikation!
    Also ich stelle 3 klare Fragen

    ErfinderDesRades schrieb:

    - kannst du Datentypen unterscheiden?
    - beherrschst du Datenmodellierung?
    - kannst du mit Databinding umgehen?
    Und als Antwort bekomme ich alles mögliche.

    Aber ich kann an deim Code schoma erkennen, dass du Datentypen nicht unterscheidest, sondern alles als String behandelst.
    Weiters scheint auch Databinding dir unbekannt zu sein.

    Aber du scheinst schon sehr weit fortgeschritten in der Datenbrei-Verarbeitung, da wirst du wohl kaum umschwenken wollen, und nochmal von Anfang an lernen, was überhaupt ein Datentyp ist und solche Sachen.

    Also was du versuchen kannst ist, beim Code aus post#1 alle Anweisungen zu entfernen, die Spalten ins DGV einbasteln.
    DGV erstellt sich seine Spalten dann nämlich automatisch.
    Also Zeilen#11 - #18 einfach löschen und gucken, ob was kommt.
    Ach das hatteste schon, und hast festgestellt, dass die Auto-Generierten Spalten unzureichend sind.
    Naja - mit denen musste aber arbeiten, nach deiner Vorgehensweise.

    Du kannst ja die DGV-Spalten vom DGV abrufen, nachdem die Autogenerierung sie generiert hat, und ihnen nachträglich iwelche hübschere Spaltenüberschriften zuweisen, nach iwelchen Kriterien.
    Aber das ist halt das Problem:
    Ein DGV was alles mögliche anzeigen soll braucht dann eine sehr komplexe Logik, die in Abhängigkeit vom grad Angezeigten die Spalten ansprechend formatiert.

    Und einiges geht halt auch garnet, etwa das Rückspeichern vorgenommener Änderungen.
    also ich (als nicht profi- möchte ich zur sicherheit anmerken ) würde mir für jeden abfrage typ (von mir aus mix aus mehreren tabellen) eine tabelle in einem typisierten dataset bauen - wobei hier dann logischer weise jede spalte den richtigen .net datentyp hat - und diese dann mit dem inhalt der sql abfrage gezielt (natürlich mit den richtig ggfls. konvertierten datentypen) in die passende tabelle des datasets einlesen.

    die tabelle des datasets kannste dann ja ganz bequem über designer an ein datagridview binden und hier alle spalten wie gewünscht formatieren.

    edit: bei den tabellen im typ dataset haste halt den vorteil dass es eine typisierte .addtblrow gibt die von vornherein verhindert dass du falsche typen einliest.
    Gruß Hannes
    Ok, verstehe.

    Zu deiner Frage, ja, ich kenne Datentypen und ihre Bedeutung :)
    Habe es zwar nicht umgesetzt, bedeutet ja nicht das man diese nicht kennt ;)

    Ist wie im richtigen leben, man weiß es besser, aber lebt selber nicht immer danach :D

    Ich werde es einfach weiter versuchen, und mir auch deinen Rat mit Datentypen zu Herzen nehmen.
    Die Lösung über ListView habe ich ja schon, es ist einfach nur eine weitere Möglichkeit was neues auszuprobieren, um auch beurteilen zu können was für einen selber besser oder schlechter ist.

    Es gibt ja nichts schlimmer wie Leute die behaupten das etwas blöd ist, ohne es jeh verwendet oder gemacht zu haben ;)

    Aber Danke für die Tipps, ich denke damit kann ich dennoch arbeiten.

    Ich finde das Forum ( die Community ) hier sehr gut und Hilfsbereit, vielen Dank nochmal.