Laden...

Datenbankupdate/Insert mit mehreren Basistabellen

Erstellt von kingpin166 vor 11 Jahren Letzter Beitrag vor 11 Jahren 2.695 Views
K
kingpin166 Themenstarter:in
8 Beiträge seit 2005
vor 11 Jahren
Datenbankupdate/Insert mit mehreren Basistabellen

verwendetes Datenbanksystem: <SQL Server 2005>
C# .Net 3.5 - Windows Forms Application

Moin,

ich möchte eine Tabelle in meiner Datenbank füllen deren Inhalt sich aber über mehrere Fremdschlüssel bestimmt. Ich wähle also vorher in einer entsprechenden Eingabemaske die Filter aus und habe dann eine SQL Anfrage mit mehreren Joins und Tabellen. Das Ergebnis lasse ich mir in einem DataGrid darstellen.
Soweit so gut.

Nun geht es aber ans Update, bzw Insert.
Mit der BindingSource komme ich nicht weiter, da ich in der Tabelle, welche ich Updaten möchte einen zusammengesetzten Schlüssel habe.
Der CommandBuilder unterstützt nur INserts und Updates auf einer Tabelle (wie sinnvoll ist das überhaupt ?? Hat man nicht mindestens immer 2 oder 3 Tabellen im Join ?).
Der TableAdapter kann auch nur mit einer Tabelle arbeiten.

Also wie kriege ich es hin ein Update bzw. Insert zu realisieren ? Unter VBA gab es das Recordset. Einfach einlesen mit zig Joins.. ändern und zack Update. Wieso geht das unter C# nicht ?

Vielen Dank

G
538 Beiträge seit 2008
vor 11 Jahren

Entweder konstruierst du deinen SQL Befehl einfach selbst (auf jeden Fall parameterisiertes SQL benutzen!) oder du schaust dir mal das Entity-Framework an - letzteres kann auch mit zusammengesetzen Schlüsseln arbeiten.

Der Vorteil der Klugheit liegt darin, dass man sich dumm stellen kann - umgekehrt ist das schon schwieriger (K. Tucholsky)
Das Problem mit Internet-Zitaten ist, dass sie oftmals zu unrecht als authentisch angenommen werden. (K. Adenauer)

3.825 Beiträge seit 2006
vor 11 Jahren

Hallo Kingpin,

Unter VBA gab es das Recordset. Einfach einlesen mit zig Joins.. ändern und zack Update. Wieso geht das unter C# nicht ?

weil unter .NET das Konzept geändert wurde und das Dataset eingeführt wurde. Das Compact Framework hat übrigens noch das Recordset 😉

Du kannst mehrere Tabellen in einem Dataset auf einmal speichern, dazu für jede Tabelle den CommandBuilder aufrufen :

public void RecInsert3(DataSet ds)
{
	DbConnection conn = CreateConnection();
	foreach (DataTable tab in ds.Tables)
	{
		DbDataAdapter da = CreateDataAdapter(conn);
		da.SelectCommand = CreateCommand("select * from " + tab.TableName + " where 0 = 1", conn);
		DbCommandBuilder cb = CreateCommandBuilder(da);
		int anzahl = da.Update(tab);
	}
	conn.Close();
}

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

F
10.010 Beiträge seit 2004
vor 11 Jahren

@BerndFfm:
Auch das CF hat kein Recordset.
Was Du meinst ist das der SqlServer Compact und damit SqlCeClient ein ResultSet beinhaltet.
Das ist aber was anderes.

@kingpin166:

Hat man nicht mindestens immer 2 oder 3 Tabellen im Join ?).

In einem Join ja, in Abfragen selten.
Wenn man sich von vornherein darauf einstellt, ist es auch sehr selten ein Problem.

K
kingpin166 Themenstarter:in
8 Beiträge seit 2005
vor 11 Jahren

Sorry vielleicht geh ich ja zu naiv an die Sache ran..

Wenn ich eine etwas komplexere Anfrage an meine Datenbank schicke, dann habe ich mind. 4 mal JOIN benutzt.

Bsp:
Select table1.a, table2.c, table4.e, table5.e from
table1 left outer join table on table1.b = table2.b inner join....

Also wo ist für dich der Unterschied zwischen Abfrage und Join ?

4.221 Beiträge seit 2005
vor 11 Jahren

Du kannst mehrere Tabellen in einem Dataset auf einmal speichern, dazu für jede Tabelle den CommandBuilder aufrufen :

Aber aufgepasst... die Reihenfolge spielt da auch eine Rolle.

Und das muss zusätzlich noch differenziert werden für Inserts und Delete. Bei reinen Updates (sofern weder Key noch ForeignKey betroffen sind spielt die Reihenfolge keine Rolle).

Gruss
Programmierhans

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

F
10.010 Beiträge seit 2004
vor 11 Jahren

@kingpin166:

  1. Abfrage ist jedes valide SQL das du zu einer DB schicken kannst.
  2. Join ist eine Verknüpfung von einzelnen Abfragen zu einer einzelnen.
    Beides geht ohne weiteres in .NET.

Du solltest Dir mal die Grundlagen und vor allem die Denkweise von ADO.NET gegenüber DAO/ADO anschauen.
Bei ADO/DAO wird der Datensatz gelockt, du stehst direkt in den Daten und kannst deswegen updaten.
ADO.NET arbeitet immer mit Verbindungslosen Daten, also nach dem lesen ist die Verbindung zu den Daten weg.

Der CommandBuilder ist ein simples construct das für Anfänger und für einfache Abfragen den entsprechenden SqlString erzeugen kann.
Sobald du mehr als eine Tabelle hast, kann der CB nicht mehr entscheiden welches Feld wohin gehört.
Dafür bist du dann zuständig und musst eben die entsprechenden SqlStrings aufbereiten.

In 90% der fälle ist der Commandbuilder weiterhin brauchbar, da die Joins ja meist lookups sind, welche ja so nicht gespeichert werden müssen.
Also reicht es ein Sql zu erzeugen was diese eine tabelle updatet.
Oder man hat Master/Detail die man in .NET auch anders aufbaut.

Und hör auf VB6/VBA und Recordsets nachzuweinen, das bringt nix und verhindert nur das du die andere Herangehensweise verstehst und benutzt.

K
kingpin166 Themenstarter:in
8 Beiträge seit 2005
vor 11 Jahren

Danke erstmal für die Antworten.
Nagut ich weine dem Recordset nicht mehr nach 😉. Es ist nur so, dass ich eine Datenbankapplikation die mit VBA in Access geschrieben wurde auf C# .Net portieren muss. Und in dem Code von VBA sieht einiges wesentlich "entspannter" und weniger aufwendig aus.

Die Konstrukte von DataSet und DataTable finde ich in .Net schon mal sehr gut gelöst.
Ich habe auch gesehen, dass es typisierte DataSets gibt, die ein paar Vorteile gegenüber den untypisierten haben.
Wenn man in C# nun mit typisierten DataSets arbeiten will muss man immer eine Projektdatenquelle angeben. Das geht auch alles sehr easy von der Hand muss ich sagen, aber ich habe ein Problem damit.
Mein Programm wird nicht mit einer Datenbank arbeiten, sondern ich muss die Möglichkeit haben die Datenbank dahinter zu wechseln (Struktur in der DB ist immer gleich). Bei der Projektdatenquelle wird irgendwo der ConnectionString abgespeichert. Wie stell ich das nun am günstigsten an, dass ich in meinem Programm sowohl den Server als auch den DB Namen wechseln kann und trotzdem mit typisierten DataSets arbeiten kann ? Der ConnectionString steht m.W. in irgendeiner Ressourcendatei in XML, aber komm ich da ran um ihn zu ändern ? Mir scheint, als sei diese Art von Programm (wechselnde Datenbanken) nicht vorgesehen. Dabei kann ich mir aber nicht vorstellen, dass man nicht den DB Server auswählen kann.. und das wäre ja das selbe Problem eigentlich.

3.825 Beiträge seit 2006
vor 11 Jahren

Du kannst beim Erzeugen der Connection einfach einen Connectionstring angeben.

Schau auch hier : [FAQ] DB-Password/Kennwort/Connection-String sicher speichern

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3