Autor Beitrag
ralph71
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 54



BeitragVerfasst: Mi 16.11.16 16:24 
Hallo,
(schon wieder ich)

ich möchte in einer DataTable einzelne Felder ändern.
In einem anderen Projekt, dessen Datenbank lokal lag funktioniert dies problemlos.
Im jetzigen Fall ist der SQL irgendwo im Netz.
Der Connect funktioniert, des werden mir die einzelnen Feldinhalte angezeigt.
Nur die Änderungen werden nicht in die Datenbank geschrieben. Warum?

Mein Code:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
            SqlConnection con = new SqlConnection("Data Source=x.x.x.x;Initial Catalog=ABC;User ID=sa;Password=XXXX");
            SqlDataAdapter sda = new SqlDataAdapter("SELECT Mein_Text FROM T_Performance", con);
            DataTable dt = new DataTable();
            sda.Fill(dt);
            foreach (DataRow row in dt.Rows)
            {
                
                try
                {
                        row["mein_Text"] = "abcde";
                        row.EndEdit();                    
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }

Ideen?

Moderiert von user profile iconChristian S.: C#-Tags hinzugefügt
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 16.11.16 16:28 
Wo is denn der Code der den geänderten Inhalt aus der DataTable wieder in die Datenbank schreibt?
ralph71 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 54



BeitragVerfasst: Mi 16.11.16 16:38 
jetzt versteh ich die Welt nicht mehr.
Dachte das reicht:
ausblenden C#-Quelltext
1:
2:
row["mein_Text"] = "abcde"
row.EndEdit();


Aber jetzt gehts nirgendwo mehr. Mir ist schon klar, dass der DataTable ein interne Tabelle ist, deren Inhalt in die Datenbank geschrieben werden muss. War der Meinung das ist row.EndEdit();
(es outet sich der Anfänger)

Sondern?

PS: schön wäre es, wenn die interne Tabelle vollständig geändert wird und dann das ganze in einem Rutsch in die Datenbank geschrieben wird. Oder soll da jeder Satz einzeln geschrieben werden?

Moderiert von user profile iconChristian S.: C#-Tags hinzugefügt
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 16.11.16 16:43 
Du hast die Daten auch nicht mit DataTable.Fill() geholt sondern über jemand anderen oder ;)
Die DataTable ist nur In-Memory die weiß nicht wo die Daten her kommen oder wo die hinsollen. Das Ding das das kann ist der DataAdapter.
Schau dir mal von deinem SqlDataAdapter die Update Methode an. Die funktioniert aber nur wenn du am SqlDataAdapter auch passende Update,Insert, Delete Statements hinterlegt hast und nicht nur den Select.

Details zum Beispiel hier
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Mi 16.11.16 17:24 
Hallo Ralf,

das mit dem SqlDataAdapter ist nicht ganz richtig - es reicht auch ein einfacher select und daraus werden dann die passenden anderen Statements erzeugt (vorausgesetzt der select bezieht sich nur auf eine Tabelle).

Und ralph71: das row.EndEdit() beendet nur den Editiermodus, d.h. die aktuell vom Anwender eingetragenen Werte werden in die DataRow übernommen - mehr nicht.
ralph71 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 54



BeitragVerfasst: Mi 16.11.16 22:21 
Dh, wenn ich über den dataadapter gehe kann ich folgendes realisieren:
Ich hole mir über einen entsprechenden select die Datensätze aus der Datenbank. Anschließend gehe ich Zeile für Zeile durch, prüfe auf bestimmte Kriterien und ändere gegebenenfalls den einzelnen Satz. Anschließend schreibe ich den geänderten Satz sofort in die Datenbank zurück. Das wäre die Vorgehensweise in Access und Recordset. Oder ich durchlaufe alle Datensätze und schreibe am Ende alle auf einmal in die Datenbank. Das meine ich ist das Vorgehen in abap und interne Tabelle unter SAP.
Wie is es denn nun? Für jeden Hinweis dankbar.....
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mi 16.11.16 23:08 
Eine DataTable würde in dem Vergleich einem disconnected Recordset entsprechen.

Wann die Daten zurückgeschrieben werden hast du selbst im Griff du kannst eine Row ändern und dann die DataTable durch den DataAdapter jagen oder du machst es nach jeder n.ten Row oder nach allen Row Änderungen. Deine freie Entscheidung.
ralph71 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 54



BeitragVerfasst: Do 17.11.16 10:14 
Danke für die Antworten. Hab ich soweit verstanden.
Jetzt sind wir leider im "Vorbete-Modus": :-(

ausblenden C#-Quelltext
1:
sda.Update(dt);					


ist nicht ausreichend. Sondern?

Moderiert von user profile iconTh69: C#-Tags hinzugefügt
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 17.11.16 10:47 
- Nachträglich durch die Entwickler-Ecke gelöscht -
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Do 17.11.16 10:48 
Update reicht immer dann aus wenn
a.) das sql so simpel war das der DataAdapter passende Statements für Insert, Update, Delete automatisch anlegen anlegen kann (in deinem Beispiel sieht dein Select SQL so simpel aus)
b.) keine Datenbank Fehler beim Ändern der Daten in der Datenbank auftreten. Es können konurierende Änderungen augetreten sein oder Trigger, Constraints, Indizes in der Datenbank das einfügen verhindern.

Um a.) zu prüfen solltest du dir zur Laufzeit mal den Inhalt der UpdateCommand Property ansehen ob die existiert und das enthaltene Update SQL Statement deiner Vorstellung entspricht.
Und bei b.) solltest du den RowUpdated Event des DataAdapters fangen und dir in den EventArgs die potentiell aufgetretenen Fehler ansehen.

Ich hatte extra mal eine ordentliche Dokumentation zu ADO.Net verlinkt. Dort auch mal das Kapitel 27 lesen. Dann bekommst du zumindest schonmal einen Überblick was es alles an der Stelle gibt und bedacht werden sollte.
ralph71 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 54



BeitragVerfasst: Do 17.11.16 11:57 
irgendwie suche ich immer noch nach der einfachen Möglichkeit.
Zum Vergleich:
In Access realisiere ich das alles in einem "5-Zeiler"
--> ich hol mir das Recordset (SELECT auch mit UNION)
--> ich gehe die Zeilen durch
--> mach eine Änderung in der Zeile
--> recordset.update
--> gehe zur nächsten Zeile
Fertig.
D.h. ich benötige keinen SQL-Update-String oder muss wie bei einem Dataset keine DataRelation bauen.

Denke ich in C# in die falsche Richtung, verwende ich das falsche Konstrukt?
Oder muss ich wirklich alles (SQL-UPDATE, DataRelation) nochmal von Hand in den C#-Code schreiben obwohl
* die Datenbank doch schon die Relationen im Bauch hat
* der SqlDataAdapter über die Row den Datensatz "in der Hand hat"

Ich bin hier so in der Findungsphase. D.h. ich bau mir ein paar Grundkonstrukte zusammen, ohne die es einfach nicht geht. Und eines davon ist eben Massenänderung im Hintergrund.

btw: Kapitel 27 habe ich gelesen, irgendwo zielt das aber an meinem Vorhaben bzw. an meiner Denke vorbei...
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4701
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Do 17.11.16 12:41 
Wie Access programmieren kannst du am besten mit Access ;)
Ado.net arbeitet aber mit allen Datenbank die einen passenden Treiber bereitstellen und nicht nur mit einem eng geschnittenen Sonderfall der so tut als würde es bestimmte Anwendungsfälle einfach nicht geben.

Zitat:
Denke ich in C# in die falsche Richtung, verwende ich das falsche Konstrukt?

Du versuchst die kleine Access Welt auf echte Datenbanken hoch zu rechnen mußt aber eben jetzt so arbeiten wie Datenbanken nunmal arbeiten und nicht nur wie Access.

Zitat:
Oder muss ich wirklich alles (SQL-UPDATE, DataRelation) nochmal von Hand in den C#-Code schreiben obwohl

Der Anfang wäre einfach mal eine ADO.Net Doku zu lesen. Ich habe einmal eine verlinkt und dann nochmal drauf hingewiesen. Der beste Weg wäre die oder eine andere Doku einfach mal zu lesen und nebenbei möglichst alles was du über Acces weißt zu vergessen. Access ist Mist sobald du an echte Problemstellungen denkst die Datenbanken nun mal lösen sollen (Multiuser umgebung, konkurierende Änderungen, echte Kontrolle darüber was wann wie passiert etc.) Access ist nur einfach weil es die meisten Probleme einfach ignoriert. Wenn du eine Einzelplatz-Singleuserumgebung im Kopf hast kannst du das Access Model weiterverfolgen aber ADO.Net wird dir dann nicht entgegenkommen. Es versucht nunmal das ganze Problem zu lösen und nicht den seltenen trivialen Fall einfach zu halten.
ralph71 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 54



BeitragVerfasst: Do 17.11.16 13:00 
Die aktuelle Lösung arbeitet mit Access und MySQL im Backend. Wir haben derzeit enorme Probleme mit dem Zurückschreiben von Datensätzen (Latenzzeiten, Datenkonflikte, usw). Wenn ich Deine Ausführungen so lese, dann scheint das logisch.
Also muss jetzt was anderes her.

Danke Dir!