Laden...

IDE stürzt ab beim SQL.UPDATE

Erstellt von Starfight vor 6 Jahren Letzter Beitrag vor 6 Jahren 5.167 Views
Thema geschlossen
S
Starfight Themenstarter:in
62 Beiträge seit 2005
vor 6 Jahren
IDE stürzt ab beim SQL.UPDATE

verwendetes Datenbanksystem: SQL Express 2016

Ich grüße euch.
Ich erstelle eine Datenbank mit einer Tabelle für Artikel. Also ArtNr, Beschreibung, Preis. etc.
Dann gehe ich her, lese eine Textdatei, wo alle Artikel (ca. 180.000) mit den entsprechenden Infos drin stehen. Danach fülle ich eine DataTable mit diesen Daten. Läuft soweit auch alles korrekt.
Die Tabelle auf der Datenbank lese ich ebenfalls ein und MERGE beide dann, um vorhandene Artikel upzudaten, neue hinzuzufügen oder nicht mehr vorhandene zu löschen.
Soll ja angeblich alles mit diesem einen Befehl gehen. Ob das wirklich so ist, sei erst mal dahingestellt.
Nach dem MERGEN will ich die Daten dann mittels UPDATE wieder in die Datenbanktabelle schreiben. Und hier passiert es. Irgendwann mal, ist immer an unterschiedlichen stellen, stürz mir die IDE einfach ab. Ohne Fehlermeldung. Einfach nur "Visual Studio muß neu gestartet werden.
Selbst wenn ich das UPDATE in TRY und CATCH setze, wird der Fehler nicht abgefangen.

Das komische ist halt auch, die IDE stürzt mal nach ca.30.000 Datensätzen ab, manchmal aber auch erst nach 180.000 Datensätzen.

Jemand eine Idee, was ich falsch mache ?

Hier mal der relevante Codeausschnitt:


comSQL = new SqlCommand("SELECT * FROM Waren", connSQL);
adapterWaren = new SqlDataAdapter(comSQL);
adapterWaren.Fill(DT_Waren);
DT_Waren.PrimaryKey = new DataColumn[] { DT_Waren.Columns[0] };
DataTable DT_Waren_NEU = DT_Waren.Clone();
DataRow ROW_Waren = DT_Waren_NEU.NewRow();

Datenzeile = null;
string[] Wa = Waren.Split(new string[] { "\n" }, StringSplitOptions.None);
int länge = Wa.Length;
progressBar1.Maximum = länge;
textBox1.Text = länge.ToString();
int zähler = 0;
progressBar1.Value = zähler;
Application.DoEvents();
foreach (string Zeile in Wa)
{
       if (Zeile != "")
       {
       Datenzeile = Zeile.Split(new string[] { "\t" }, StringSplitOptions.None);
       ROW_Waren[0] = Convert.ToInt32(Datenzeile[0]);      
       ROW_Waren[1] = Datenzeile[1];                       
       ROW_Waren[2] = Datenzeile[2];                       
       ROW_Waren[3] = Convert.ToInt64(Datenzeile[3]);      
       ROW_Waren[4] = Datenzeile[4];                       
       ROW_Waren[5] = Convert.ToInt16(Datenzeile[5]);      
       ROW_Waren[6] = Convert.ToDecimal(Datenzeile[6].Replace(".", ","));    
       ROW_Waren[7] = Convert.ToDecimal(Datenzeile[7].Replace(".", ","));    
       ROW_Waren[8] = Datenzeile[8];                       
       ROW_Waren[9] = Datenzeile[9];                       
       ROW_Waren[10] = Datenzeile[10];                     
       ROW_Waren[11] = Datenzeile[11];                     
       ROW_Waren[12] = Convert.ToDecimal(Datenzeile[12].Replace(".", ","));  
       ROW_Waren[13] = DateTime.Now;                     

       DT_Waren_NEU.Rows.Add(ROW_Waren);
       ROW_Waren = DT_Waren_NEU.NewRow();
       zähler += 1;
       progressBar1.Value = zähler;
       label1.Text = zähler.ToString();
       Application.DoEvents();
       }
}


this.Text = "Update Datenbank...";
Application.DoEvents();
DT_Waren.Merge(DT_Waren_NEU);
progressBar2.Maximum = DT_Waren.Rows.Count;
label2.Text = (DT_Waren.Rows.Count).ToString();
adapterWaren.RowUpdating += new SqlRowUpdatingEventHandler(OnRowUpdated);
Zähler2 = 0;
adapterWaren.Update(DT_Waren);
adapterWaren.RowUpdating -= new SqlRowUpdatingEventHandler(OnRowUpdated);
this.Text = "Fertig";


        private void OnRowUpdated(object sender, SqlRowUpdatingEventArgs e)
        {
            Zähler2 += 1;
            label1.Text = Zähler2.ToString();
            progressBar2.Value = Zähler2;
            Application.DoEvents();
        }

16.841 Beiträge seit 2008
vor 6 Jahren

Puh.... der ganze Code ist suboptiomal. Um es freundlich zu sagen 😉
Auch wenn ich schon Application.DoEvents (Warum DoEvents Mist ist!) sehe, ist das mehr als nur ein Hinweis, dass hier etwas gewaltig im Argen ist.

Bei so vielen Elementen im Speicher im Zusammenhang mit der DataTable riecht das für mich nach einer OutOfMemory Exception, die dann die IDE in die Tiefe zieht.
So aus der Ferne aber auch nicht genau diagnostizierbar; wir haben ja auch keine Glaskugel und sind noch weiter weg davon als Du 😉)

Aber hier ist dringend eine Refaktorierung notwendig.

D
985 Beiträge seit 2014
vor 6 Jahren

Für so ein Massengeschäft ist das DataTable.Merge nicht wirklich geeignet.

  1. Nimm die Library von http://filehelpers.net und lies damit die Daten aus der Datei (das geht auch schön Zeile für Zeile)
  2. Das Merge kann auch direkt auf dem SQL-Server erfolgen. Alle Daten aus der Datei in eine temporäre Tabelle schreiben und dann mit der eigentlichen Tabelle mergen.
S
Starfight Themenstarter:in
62 Beiträge seit 2005
vor 6 Jahren

Danke für deine Antwort Abt, aber...

Puh.... der ganze Code ist suboptiomal. Um es freundlich zu sagen 😉

Der Code befindet sich in der Entwicklung. Das da weder Fehlerabfang noch Optimierung stattgefunden haben, sollte doch eigentlich klar sein.

Auch wenn ich schon Application.DoEvents (
>
) sehe, ist das mehr als nur ein Hinweis, dass hier etwas gewaltig im Argen ist.

Aha, weil ?
Wie gibst Du den die Kontrolle an andere Tasks zurück, damit z.B: auch ein Bildschirmrefresh stattfinden kann ?
Natürlich kann ich so etwas eventuell auch eleganter und damit sicher auch Aufwendiger lösen, aber wie gesagt. Während der Entwicklung ist mir Eleganz eher egal. Da will ich sehen, ob fas, was ich mir ausgedacht habe, funktioniert. Alles andere dann erst später.

Bei so vielen Elementen im Speicher im Zusammenhang mit der DataTable riecht das für mich nach einer OutOfMemory Exception, die dann die IDE in die Tiefe zieht.

Glaube ich nicht dran, weil, wie geschrieben, es auch schon mal nach nur 10.000 Datensätzen oder mal nach 50.000 Datensätzen und eben auch erst bei 180.000 Datensätzen passiert.
Zudem wird mir in der IDE beim Debuggen doch angezeigt, wie viel Speicher gerade belegt wird. Und da ging es bisher niemals über 500 MB hinaus, eher deutlich darunter.
Aber ich werde mal in dieser Richtung forschen. Man weiß ja nie.

So aus der Ferne aber auch nicht genau diagnostizierbar; wir haben ja auch keine Glaskugel und sind noch weiter weg davon als Du 😉)

Du, ich weiß, das sowas schwierig ist. Es gibt aber auch die Fälle, wo einer dann sagt "Hey, genau sowas hatte ich auch mal und habe es so und so lösen können."

Für so ein Massengeschäft ist das DataTable.Merge nicht wirklich geeignet.

Hmmm. Weil ?
Ich fand es irgendwie sehr geeignet, das im Programm eine Tabelle existiert, die genauso aussieht, wie die Tabelle in der Datenbank und quasi nur gefüllt werden muß.
Dann noch mit nur einem Befehl UPDATE, DELETE und ADD gleichzeitig auszuführen, fand ich ebenfalls gut. Aber ich höre mir da immer gern die Meinung anderer an.

  1. Nimm die Library von
    >
    und lies damit die Daten aus der Datei (das geht auch schön Zeile für Zeile)

Ich bin nicht wirklich ein Freund von externen Routinen. Ich will beim Programmieren ja auch was lernen und es erleichtert meiner Meinung nach die Fehlersuche, wenn man etwas selbst geschrieben hat, aber ich schaue es mir dennoch mal an.

  1. Das Merge kann auch direkt auf dem SQL-Server erfolgen. Alle Daten aus der Datei in eine temporäre Tabelle schreiben und dann mit der eigentlichen Tabelle mergen.

Ähm, sorry, aber was bitte mach ich den anderes ?
Oder meinst Du, auf dem SQL Server eine extra Tabelle anlegen, da mühsam ALLES rein schreiben und dann dem SQL Server den Befehl zum Mergen geben ?
Genau das will ich doch eigentlich vermeiden. So wie ich das verstanden habe, werden bei mir nur die Änderungen zum SQL Server geschickt und nicht alle Daten.

16.841 Beiträge seit 2008
vor 6 Jahren

Naja, was soll man dazu noch sagen? Wenn Du alles verteufelst und abblockst bzw. nicht mal in Betracht ziehst; warum suchst Du dann nach Hilfe? 🤔
Also ich für meinen Teil bin nach der Antwort raus.

S
Starfight Themenstarter:in
62 Beiträge seit 2005
vor 6 Jahren

Bitte was ? Wo bitte lehne ich den alles ab ? Hast Du meine Antwort überhaupt gelesen ?
Und nur, weil eine Antwort von Dir kommt, muß ich die nicht bedingungslos annehmen. Ich dachte, es ist ein Diskussionsforum, wo man auch mal über das für und wieder reden kann.
Meinungsaustausch halt. Aber wenn hier nur eine Meinung zählt, dann bin ich wohl wirklich im falschen Forum.
Sorry für die Belästigung.

D
985 Beiträge seit 2014
vor 6 Jahren

Ich denke mal, weil er deine Antwort gelesen hat, kommt er zu diesem Resultat.

16.841 Beiträge seit 2008
vor 6 Jahren

Davon abgesehen, dass der Ton die Musik spielt...Du nimmst ja schon den einfachsten Rat nicht an bzw. blockst ihn ab, was viel schlimmer ist. Sehen wir ja am DoEvents Thema.
Du fragst warum, obwohl genau das im verlinkten Thema steht. Auch bei den FileHelpers blockst Du ja den Einsatz von externen Bibliotheken ab mit der Begründung des Not-invented-here-Syndrom.
Lernen schön und gut; aber erntest Du auch Weizen von Hand wenn Du Mehl kaufst?

Wie man ordentlich DoEvents ersetzt steht zB neben vielen weiteren Grundlagenthemen einfach in der FAQ.
[FAQ] Controls von Thread aktualisieren lassen (Control.Invoke/Dispatcher.Invoke) bzw. [FAQ] Warum blockiert mein GUI? davon abgesehen geht es noch einfacher mit async/await; aber damit zu kommen wenn wir uns um DoEvents streiten: absolut sinn frei.

Ist ja okay, dass Du hier nicht jede Antwort bedingungslos annimmst; aber einfach pauschal mit "Glaube ich nicht" zu antworten. Keine Antwort ist absolut. Auch meine nicht.
Aber: was soll man auf diese Antwort da noch als Helfer sagen? Ich bin Dir keine Rechenschaft schuldig und muss Dir eine potentielle Lösung nicht beweisen.
Ich muss Dir nicht mal antworten - tue es aber mit dem Hintergrund des Helfens.
Glaubst Du wir antworten Dir, um Dich auf falsche Fährten zu bringen? Was hätte ich davon?
Tja.. so ist der Sinn des Forums verfehlt. Und daher auch meine vorherige Antwort.

PS: auch in der Entstehung von Code sollte man die Qualität nicht vernachlässigen.
Kein Code hält sich so lange wie "kurzfristige Lösungen" - die einem später um die Ohren fliegen.
Nur, dass der Code Dir hier schon um die Ohren fliegt.

5.658 Beiträge seit 2006
vor 6 Jahren

Hi Starfight,

falls du dich über die Reaktionen auf deine Antwort wunderst, hier mal ein kleines Gedankenspiel. Stell dir vor, jemand fragt dich auf der Straße, wie er zum Bahnhof kommt. Du erklärest es ihm, aber er antwortet mit "Aha, weil ?", sagt, daß er immer in der anderen Richtung unterwegs ist, und verabschiedet sich mit "Sorry für die Belästigung". Wie freundlich würdest du dabei bleiben?

Weeks of programming can save you hours of planning

S
Starfight Themenstarter:in
62 Beiträge seit 2005
vor 6 Jahren

Davon abgesehen, dass der Ton die Musik spielt...Du nimmst ja schon den einfachsten Rat nicht an bzw. blockst ihn ab, was viel schlimmer ist. Sehen wir ja am DoEvents Thema.

Hast Du meine Begründung gelesen ?

Du fragst warum, obwohl genau das im verlinkten Thema steht.

Tja, und ich frage immer noch. Ich habe den verlinkten Beitrag sehr wohl gelesen und festgestellt, das er auf mich bzw. das kleine Programm in keinster weise zutrifft.
Wie ich bereits schrieb, das Programm ist in der Entwicklung und um für sich selbst den Ablauf sichtbarer zu machen, finde ich den Einsatz von DoEvents durchaus legitim, vor allem wenn alles, was in dem von Dir angesprochenen Thread beschrieben steht, auf mein Programm überhaupt nicht zutrifft.
Ich beende die Form nicht einfach und wenn doch, bin ich mir bewußt, das es zu einem Absturz kommen kann.

Auch bei den FileHelpers blockst Du ja den Einsatz von externen Bibliotheken ab mit der Begründung des
>
.

Falsch. Ich sag ja, DU hast meinen Text nicht ausreichend gelesen.
Ich zitiere meine Antwort nochmal und mach den entsprechenden Teil für dich deutlich:

Ich bin nicht wirklich ein Freund von externen Routinen. Ich will beim Programmieren ja auch was lernen und es erleichtert meiner Meinung nach die Fehlersuche, wenn man etwas selbst geschrieben hat, aber ich schaue es mir dennoch mal an.

Sorry, aber nur, weil man von etwas kein großer Freund ist, heißt das nicht, das man es generell ablehnt.

Wie man ordentlich DoEvents ersetzt steht zB neben vielen weiteren Grundlagenthemen einfach in der FAQ.

Hast Du das selbst mal gelesen ?
Da steht gleich vorne an:

Alle Zugriffe auf GUI-Elemente (Controls, Form u.ä.) müssen aus dem Thread heraus erfolgen, der sie erzeugt hat.

Und jetzt nochmal. Das ist bei meinem Programm gegeben, Es wird niemals meinen heimischen PC verlassen, sondern ausschließlich hier laufen. UND, es befindet sich in der Entwicklung. Da sind diverse DoEvents nur zum sehen, wie das Programm abläuft, ob es das macht, was man sich gedacht hat.
Das heißt NICHT, das die für immer und ewig da drin bleiben werden.

Ist ja okay, dass Du hier nicht jede Antwort bedingungslos annimmst; aber einfach pauschal mit "Glaube ich nicht" zu antworten.

Ich habe meine Aussage BEGRÜNDET.

Aber: was soll man auf diese Antwort da noch als Helfer sagen? Ich bin Dir keine Rechenschaft schuldig und muss Dir eine potentielle Lösung nicht beweisen.

Richtig. Es ist hier en Meinungsaustausch. Du hast deien Meinung geäußert, ich habe diese mit meiner Meinung belegt. Wo ist nun das Problem ?
In einer Diskussion erwarte ich, das man dann darüber redet und mit möglichen Beweisen seine Meinung untermauert. Aber von Dir kommt immer nur "Ich habe gesagt, Du glaubst nicht, also ende"

PS: auch in der Entstehung von Code sollte man die Qualität nicht vernachlässigen.
Kein Code hält sich so lange wie "kurzfristige Lösungen" - die einem später um die Ohren fliegen.
Nur, dass der Code Dir hier schon um die Ohren fliegt.

Da hast Du sicher recht. Aber ich muß einen Code in der Entwicklungsphase auch nicht unnötig verkomplizieren.
Und ich denke, das der Streit, ob DoEvents während der Entwicklung nun zulässig ist oder nicht, in einen anderen Thread gehört.
Hier geht es nur darum, warum ein simples SQLAdapter.Update(Datatable) zu einem Absturz führt und ich bin mir zu 100% sicher, das es NICHT am DoEvents liegt.
Beweisen kann ich das auch damit, das ich alle DoEvents ausgeklammert hatte und es dennoch abstürzt.
Wäre also klasse, sich auf das eigentliche Thema zu konzentrieren, als um unwichtiges Zeugs.

S
Starfight Themenstarter:in
62 Beiträge seit 2005
vor 6 Jahren

Hi Sparkle
Nein, ich wundere mich nicht über seine Antwort. Ich wundere mich nur, warum er mich Sachen Unterstellt, die nicht stimmen.
Aber darauf bin ich ja in meinem vorherigen Text eingegangen.

D
985 Beiträge seit 2014
vor 6 Jahren

Niemand behauptet, dass DoEvents die Ursache ist, aber bei der Verfügbarkeit von async/await ist es schon sehr verwunderlich, wenn das nicht bzw. DoEvents überhaupt verwendet wird.

Was läuft in deinem Code generell falsch:

Die Daten aus der Datei liegen mindestens 3-4 mal im Speicher:

  1. In string Waren
  2. In string[] Wa
  3. In DataTable DT_Waren_NEU
  4. Anteilig in DataTable DT_Waren nach dem Merge

Die komplette Tabelle vom Server ist ja auch noch im Speicher sowie die Änderungshistorie nach dem Merge.

Du aast mit dem RAM herum, als ob du keine Limitierung hättest. (64-Bit Prozess?, ≥32 GB RAM?, Speicherauslastung im System ok?, Speicherfragmentierung ok?)

Wenn ich so etwas lösen müsste, dann würde ich dafür sorgen, dass sich immer nur ein ganz kleiner Teil (eine Zeile aus der Datei) im Speicher befindet und die Hauptlast der SQL-Server zu tragen hat. Der kann mit Daten auch viel besser umgehen und Merge kennt der auch noch.

Das bekommt dann jeder 32-Bit Prozess trotz Speicherfragmentierung und x GB großer Datei zuverlässig verarbeitet.

S
Starfight Themenstarter:in
62 Beiträge seit 2005
vor 6 Jahren

aber bei der Verfügbarkeit von async/await ist es schon sehr verwunderlich, wenn das nicht bzw. DoEvents überhaupt verwendet wird.

Ich weiß nicht, was mir ein ASYNC zum gegenwärtigen Zeitpunkt helfen sollte.
Das SQLDataAdapter.UPDATE blockiert die Anwendung und.....DAS SOLL SIE AUCH.
Es werden Daten in der Datenbank aktualisiert. Ein weiterarbeiten wäre hier eventuell fatal. Es würde dann eventuell genau das eintreten, was bei DoEvents als so fatal dargestellt wird. Der eine Thread aktualisiert noch die Datenbank und der Benutzer löscht irgendwas in der Datenbank.
Es geht hier doch rein nur darum, das die Anzeige refresht wird. Warum macht ihr darum so ein aufheben ?

Was läuft in deinem Code generell falsch:

Die Daten aus der Datei liegen mindestens 3-4 mal im Speicher:

  1. In string Waren
  2. In string[] Wa
  3. In DataTable DT_Waren_NEU
  4. Anteilig in DataTable DT_Waren nach dem Merge

Hmmm, Du hast recht.
string Waren könnte ich vor dem Update tatsächlich löschen.
string[] Wa tatsächlich auch, da ja bereits alles in die temporäre Tabelle eingelesen wurde.
Werde ich gleich mal in Angriff nehmen.

Du aast mit dem RAM herum, als ob du keine Limitierung hättest. (64-Bit Prozess?, ≥32 GB RAM?, Speicherauslastung im System ok?, Speicherfragmentierung ok?)

Naja, weißt. Die einzulesenden Daten sind 33 MB groß. 33 mal 4 = 132 MB. Ich denke nicht, das ich da mit irgendeinem Speicherproblem rechnen muß.

Wenn ich so etwas lösen müsste, dann würde ich dafür sorgen, dass sich immer nur ein ganz kleiner Teil (eine Zeile aus der Datei) im Speicher befindet und die Hauptlast der SQL-Server zu tragen hat. Der kann mit Daten auch viel besser umgehen und Merge kennt der auch noch.

Tja, das sehe ich anders.
Der Vorteil an der Tabelle im Speicher und dem Update soll ja eben sein, das NUR die wirklich geänderten Zeilen wieder zum SQLServer übermittelt werden.
Wenn ich erst auf dem SQLServer eine TMP_Tabelle anlege, in die dann ALLE Daten schreiben muß, um dann ein MERGE auszuführen, halte ich das für Kontraproduktiv.
Warum 180.000 Zeilen zum SQL Server übertragen, wenn es eventuell nur bei 10.000 notwendig ist ?

PS: Das Programm läuft gerade und die Speicherauslastung wird mir im Debugger mit knapp 285 MB angezeigt. Permanent.
Ich denke also nicht, das ich mir hier sorgen wegen Speicherauslastung machen muß. Oder übersehe ich etwas ?

W
955 Beiträge seit 2010
vor 6 Jahren

Was passiert eigentlich wenn du die Anwendung ausserhalb der IDE laufen lässt?

D
985 Beiträge seit 2014
vor 6 Jahren

Anscheinend ist dir nicht bewusst, was bei DoEvents alles passiert.

Es werden alle ausstehenden Ereignisse abgearbeitet. z.B. irgendwelche Klicks auf Buttons, etc. Hämmert der Benutzer auf irgendwelche Buttons, dann wird das beim Aufruf von DoEvents verarbeitet. Und wenn das alles passiert ist, dann kehrt DoEvents wieder zurück.

Du musst also genau wie bei async/await dafür sorgen, dass der Benutzer nur das ausführen darf, was auch aktuell ausgeführt werden soll. Also in der Hinsicht kein Unterschied.

Der große Unterschied bei async/await ist aber (bei geschickter Anwendung), dass deine GUI nicht blockiert und wenn du die GUI aktualisierst, dann wird dein Task nicht blockiert. Beide laufen also flüssig nebeneinader her. Das nennt man dann Nebenläufigkeit.

Mit den Daten zum Server:

Kann man sehen wie man möchte:

Ich übertrage die Daten zum Server und dort wird entschieden, was er davon übernehmen muss.
Du holst dir alle Daten vom Server (wieviel das auch immer sein muss) und entscheidest dann welche Daten du zum Server übertragen willst.

Rein vom Datenvolumen, was da bewegt wird, erzeugt mein Ansatz weniger Traffic.

Und bei meinem Ansatz würde sogar ein Rasberry PI die Aufgabe in anähernd der gleichen Geschwindigkeit durchführen, wie ein High-End-Rechner.

S
Starfight Themenstarter:in
62 Beiträge seit 2005
vor 6 Jahren

Was passiert eigentlich wenn du die Anwendung ausserhalb der IDE laufen lässt?

Das Programm stürzt einfach ab.

Anscheinend ist dir nicht bewusst, was bei DoEvents alles passiert.

Ich dachte bisher, eigentlich schon.
Und alles, was Du dazu geschrieben hast, war mir auch schon bekannt.
Ändert aber nichts daran, das meine Anwendung immer noch nur in der Entwicklung ist und ich die Anwendung von DoEvents zum refresh der Anzeige nach wie vor für ok halte.
Wenn die Routine dann mal funktioniert, ist es ein ganz anderes Thema, wie ich das dann löse. Aber während der Entwicklung bin ich für einfachheit.

Ich übertrage die Daten zum Server und dort wird entschieden, was er davon übernehmen muss.
Du holst dir alle Daten vom Server (wieviel das auch immer sein muss) und entscheidest dann welche Daten du zum Server übertragen willst.

Und wie kontrollierst Du, ob das, was Du programmiert hast, auch richtig läuft ?
Solange meine Daten lokal in der IDE verarbeitet werden, kann ich jederzeit mal reinsehen, ob alles so ist, wie ich es mir vorstelle.
Halte ich vom Ansatz her für einfacher.
Wenn das mal alles richtig läuft, ja, ich glaube, dann hat deine Methode durchaus Vorteile.

So, nun zur Lösung ? des Problems.
Ich habe die Routine mal soweit umgeschrieben, das er immer in Blöcken zu 40.000 Datensätzen einen Merge und dann Update macht. Und siehe da, es läuft anstandslos durch.
Heißt das nun, das ein Update mit großen Datenmengen, hier ca. 33 MB, nicht klar kommt ? Würde mich aber doch etwas verwundern.

Oder, was mir eher wahrscheinlich erscheint, das mein Programm beim Update die Daten schneller sendet, als der SQL Server die aufnehmen und verarbeiten kann ?
Aber läuft da nicht eine Art Synchronisation / Handshake ?
Darüber habe ich bisher nichts finden können.

1.040 Beiträge seit 2007
vor 6 Jahren

Und wie kontrollierst Du, ob das, was Du programmiert hast, auch richtig läuft ?
Solange meine Daten lokal in der IDE verarbeitet werden, kann ich jederzeit mal reinsehen, ob alles so ist, wie ich es mir vorstelle.
...
Wenn das mal alles richtig läuft, ja, ich glaube, dann hat deine Methode durchaus Vorteile.

Du kontrollierst dann aber doch nur den Teil den du in der IDE schreibst, und sagst dann irgendwann "passt". Dann lagerst du den Merge in den Server aus, wer sagt dir dann, dass das alles funktioniert? 🤔
Du kannst auch auf dem Server Daten vergleichen, wenn du dort den Merge einbaust.

D
985 Beiträge seit 2014
vor 6 Jahren

Wenn dir das alles bekannt ist, dann verstehe ich deine bisherige Argumentation gegen async/await und für DoEvents nicht.

Und deine Aussage

Das SQLDataAdapter.UPDATE blockiert die Anwendung und.....DAS SOLL SIE AUCH.

ist bei deinem Code

  
adapterWaren.RowUpdating += new SqlRowUpdatingEventHandler(OnRowUpdated);  
Zähler2 = 0;  
adapterWaren.Update(DT_Waren);  
adapterWaren.RowUpdating -= new SqlRowUpdatingEventHandler(OnRowUpdated);  
this.Text = "Fertig";  
  
  
        private void OnRowUpdated(object sender, SqlRowUpdatingEventArgs e)  
        {  
            Zähler2 += 1;  
            label1.Text = Zähler2.ToString();  
            progressBar2.Value = Zähler2;  
            Application.DoEvents();  
        }  
  

ist schlichtweg falsch, denn durch das Application.DoEvents(); in OnRowUpdated durchbrichst du selber diese Blockade.

Und wie kontrollierst Du, ob das, was Du programmiert hast, auch richtig läuft ?

Da nehme ich Unit- und Integration-Tests und erfreue mich an den grünen Haken (sofern diese denn auftauchen). Bei rot muss ich halt noch aktiv werden.

Anyway ...

Ich vermute mal, dein Prozess läuft als 32-bit Anwendung und da gibt es diese 2GB Grenze.
Gleichzeitig gibt es aber auch noch die Speicher-Fragmentierung und das kann zu OutOfMemory führen, obwohl rein rechnerisch noch RAM verfügbar wäre, aber nicht mehr als zusammenhängender Block der der Anforderung entspricht.

Versuche also die Anwendung als 64-Bit Prozess laufen zu lassen.

S
Starfight Themenstarter:in
62 Beiträge seit 2005
vor 6 Jahren

Du kontrollierst dann aber doch nur den Teil den du in der IDE schreibst, und sagst dann irgendwann "passt". Dann lagerst du den Merge in den Server aus,
Soweit Ok.

wer sagt dir dann, dass das alles funktioniert? 👶
Nun, eine Abfrage, die ich in der IDE erarbeitet habe und da funktioniert, sollte dann auf dem Server doch genauso funktionieren.

Du kannst auch auf dem Server Daten vergleichen, wenn du dort den Merge einbaust.
Ja, in dem ich mir dann ALLE Daten wieder runter lade oder mit dem SQL Managment Studio arbeite. Nur, warum sollte man das in der Entwicklungsphase tun, wo der Code eventuell noch zigmal geändert wird ?
In der IDE sehe ich die Änderungen meiner Datenbankbefehle unmittelbar in der entsprechenden DataTable.

Wenn dir das alles bekannt ist, dann verstehe ich deine bisherige Argumentation gegen async/await und für DoEvents nicht.
Tja, so geht es mir mit deinen Argumenten FÜR ein Async.
Auch deine weiteren Ausführungen lassen mich vermuten, das Du nicht verstehen willst, um was es mir geht.
Aber ich versuche es noch einmal.
Das Programm ist in der Entwicklung. Es wird garantiert kein Anwender wie wild auf der Tastatur rumhämmern und es wird auch garantiert niemand einfach das Fenster schließen.
Während die Datenbank mit neuen Werten gefüllt bzw. vorhandene aktualisiert werden, soll das Programm auch gar nicht weiter laufen. Es soll definitiv gewartet werden, bis alle Daten verarbeitet wurden.
Das man diese Routine später mal in einen anderen Thread auslagert, kein Thema. Nur muß ich dann auch für Sperren sorgen, das ein anderer, der das Programm auch nutzt, nicht auf die Datenbank zugreifen kann.
Nur, wozu JETZT der ganze Aufwand, wenn es so wesentlich einfacher geht.

ist schlichtweg falsch, denn durch das Application.DoEvents(); in OnRowUpdated durchbrichst du selber diese Blockade.
Ja und ? Wo ist da dein Problem mit ?
Was ist so schwer daran zu verstehen, das während die Datenbank mit Daten gefüllt wird, sowieso nicht mit dem Programm weiter gearbeitet wird und das DoEvents nur und ausschließlich dazu da ist, dass das Label seine Daten auch aktualisieren kann.

Sorry, aber ich denke, hier wird aus einer winzigen Mücke ein gewaltiger Elefant gemacht.

Ich vermute mal, dein Prozess läuft als 32-bit Anwendung und da gibt es diese 2GB Grenze.
Oha, welche 2 GB Grenze ? Ich kenne eine 4 GB Grenze bei 32 Bit Systemen. Aber 2 GB ?

Aber Du hast tatsächlich Recht. Compiliert wird es als "Any CPU". Also durchaus möglich, das es nur mit 32 Bit arbeitet.
Das er kein ausreichend frees RAM findet, halte ich für sehr unwahrscheinlich. 16 GB RAM sind verbaut und da die Daten ja nur 32 MB groß sind, sollte er auch dann noch freies zusammenhängendes RAM finden, wenn ich Word, Excel und nen Browser aufmache.
Aber ja, hätte, könnte, wäre soll man ausschließen, also werde ich mal mit 64 Bit versuchen und mal vorher ne GC auslösen.

1.040 Beiträge seit 2007
vor 6 Jahren

Nun, eine Abfrage, die ich in der IDE erarbeitet habe und da funktioniert, sollte dann auf dem Server doch genauso funktionieren.

Du hast aber keine Abfrage, die du dann auf den Server schiebst.
Es geht mir um den Unterschied zwischen DataTable.Merge und MERGE (Transact-SQL) (@Sir Rufo: den Merge-Befehl auf dem Server meinst du doch?) und der unten getätigten Aussage.

Wenn du den DataTable.Merge-Befehl nutzt, testest du natürlich diesen und stellst dann irgendwann fest: ja, das klappt alles ("Wenn das mal alles richtig läuft").
In dem Moment sieht dann du Vorteile den Merge auf dem Server durchzuführen. Dann musst du das aber auch nochmal neu programmieren und testen. Wie kontrollierst du da, ob das, was du programmierst, richtig läuft?

Kurz gesagt: wenn du Operationen auf einem Server durchführst, wirst du so oder so nicht in der IDE sehen, ob das Programmierte richtig ist, d.h. du musst auch mal auf den Server schauen.

Ich übertrage die Daten zum Server und dort wird entschieden, was er davon übernehmen muss.
Du holst dir alle Daten vom Server (wieviel das auch immer sein muss) und entscheidest dann welche Daten du zum Server übertragen willst.
Und wie kontrollierst Du, ob das, was Du programmiert hast, auch richtig läuft ?
Solange meine Daten lokal in der IDE verarbeitet werden, kann ich jederzeit mal reinsehen, ob alles so ist, wie ich es mir vorstelle.
Halte ich vom Ansatz her für einfacher.
Wenn das mal alles richtig läuft, ja, ich glaube, dann hat deine Methode durchaus Vorteile.

D
985 Beiträge seit 2014
vor 6 Jahren

Oha, welche 2 GB Grenze ? Ich kenne eine 4 GB Grenze bei 32 Bit Systemen. Aber 2 GB ?

Ist dokumentiert: Memory Limits for Windows and Windows Server Releases

16.841 Beiträge seit 2008
vor 6 Jahren

Du kommst in ein Forum mit der Erwartung, dass die Leute Dir potentielle Fehler und Verbesserungen als Feedback zurück liefern.
Das passiert auch und Du sagst inhaltlich "Deine Argumente zählen für mich nicht". Ich würde mir als Helfer bei so einer Rückantwort einfach nur verarscht vorkommen.

Bist Du sicher, dass das Forum und das Konzept wirklich der richtige Platz für Dich ist?
Ich sag das so deutlich sehr selten und verhalte mich am liebsten neutral und liberal: aber hier finde ich es absolut frech, wie Du mehr oder minder erwartest, dass die Leute Zeit in die Hilfe Deines Problems stecken und Du die Leute so abkanzelst - und ja ich habe Deinen Jahrgang im öffentlichen Profil durchaus gesehen..

Entweder Du benimmst Dich nun so, dass das einem Forum auch im Ton angemessen wird - und damit sparst Du Dir in Zukunft so Aussagen wie "Wo ist Dein Problem?" als Antwort eines Verbesserungsvorschlags; oder ich mach die Sache hier zu und dann hat sich das hier gegessen.

S
Starfight Themenstarter:in
62 Beiträge seit 2005
vor 6 Jahren

Nun, eine Abfrage, die ich in der IDE erarbeitet habe und da funktioniert, sollte dann auf dem Server doch genauso funktionieren.

Wenn du den DataTable.Merge-Befehl nutzt, testest du natürlich diesen und stellst dann irgendwann fest: ja, das klappt alles ("Wenn das mal alles richtig läuft").
In dem Moment sieht dann du Vorteile den Merge auf dem Server durchzuführen. Dann musst du das aber auch nochmal neu programmieren und testen. Wie kontrollierst du da, ob das, was du programmierst, richtig läuft?

Du versteifst dich zu sehr auf den einen Befehl. Ich baue eine DataTable auf, im eventuell auch mehrere Aktionen mit dieser durchzuführen und dann irgendwann mal später die Daten mittels Update in die Datenbank zu schreiben.

Kurz gesagt: wenn du Operationen auf einem Server durchführst, wirst du so oder so nicht in der IDE sehen, ob das Programmierte richtig ist, d.h. du musst auch mal auf den Server schauen.

Sicher, keine Frage. Aber mal ein einfaches Beispiel:
Ich lese Daten aus einer Textdatei ein. Nach deinem vorgehen würde ich nun die gesamten Daten zum Server übertragen, dort ein Merge ausführen und muß jetzt mein Hauptprogramm so lange pausieren, bis das erledigt ist.
Weil, dann kommt eine Routine, die eventuell wieder Datensätze löscht oder gar noch Änderungen an bestehenden Datensätzen durchführt.
Hier halte ich es für besser, das erst mal alles lokal in einer Datatable zu erledigen und dann mit einem Befehl die Daten in die Datenbank zu schreiben.

Oha, welche 2 GB Grenze ? Ich kenne eine 4 GB Grenze bei 32 Bit Systemen. Aber 2 GB ?

Ist dokumentiert:
>

Also ich sehe da nur die normalen 4GB Grenzen, bzw 3,x GB bei 32 Bit.
Kernel-mode virtual address space <- Nutze ich sicher nicht.
User-mode virtual address space for each 32-bit process -> egal ob 32 Bit oder 64 Bit
Nonpaged pool -> auch egal, ob 32 bit oder 64 bit

Aber gut, brauchen wir nicht drüber streiten, auch bei 64 bit stürzt das Update ab, während es läuft, wenn ich die Daten in kleinere Pakete verpacke.

D
985 Beiträge seit 2014
vor 6 Jahren

Wenn das Lesen schon nicht mehr funktioniert, dann ist es wirklich vergeblich.

(Ich habe dir die betreffende Stelle mal in orange markiert)

Dieses gehört allerdings zum absoluten Basiswissen der Programmierung.

S
Starfight Themenstarter:in
62 Beiträge seit 2005
vor 6 Jahren

Du kommst in ein Forum mit der Erwartung, dass die Leute Dir potentielle Fehler und Verbesserungen als Feedback zurück liefern.
Das passiert auch und Du sagst inhaltlich "Deine Argumente zählen für mich nicht". Ich würde mir als Helfer bei so einer Rückantwort einfach nur verarscht vorkommen.

Liegt dann wohl an deinem mangelnden Verständnis von einer Diskussion.
Ich habe ganz sicher nirgendwo gesagt "deine Argumente zählen nicht", sondern "ich sehe das anders" und gebe meine Begründung dazu. Man tausch seine Meinung aus. GEGENSEITIG.

Bist Du sicher, dass das Forum und das Konzept wirklich der richtige Platz für Dich ist?

Bin ich. Weil ich mit anderen hier relativ problemlos Reden konnte, außer mit Dir halt.

Entweder Du benimmst Dich nun so, dass das einem Forum auch im Ton angemessen wird - und damit sparst Du Dir in Zukunft so Aussagen wie "Wo ist Dein Problem?" als Antwort eines Verbesserungsvorschlags; oder ich mach die Sache hier zu und dann hat sich das hier gegessen.

Ah, man darf also nicht nachfragen, worin jemand ein Problem bei einer bestimmten Sache sieht. Verstehe. Eine Frage bekommt eine Antwort und wenn man darüber Diskutieren will, soll man eher die Klappe halten und woanders hin gehen.
Sorry, das ist NICHT mein Verständnis einer Diskussion.

Man mag ja über DoEvents denken, wie man will. Aber ich muß deswegen nicht die Meinung anderer Akzeptieren, wenn ich denke, das es in meinem speziellen Fall völlig unproblematisch ist.

5.658 Beiträge seit 2006
vor 6 Jahren

Wenn du sowieso alles besser weißt, und jeden Verbesserungshinweis als persönlichen Angriff wertest, warum fragst du dann überhaupt erst hier im Forum nach?

Fachlich ist ja alles gesagt, was zu deinem Code zu sagen ist. Alles andere führt zu nichts, daher mache ich hier zu.

Bitte beachte zukünftig [Hinweis] Wie poste ich richtig?

Weeks of programming can save you hours of planning

Thema geschlossen