Laden...
S
Starfight myCSharp.de - Member
Programmierer Hückelhoven Dabei seit 08.10.2005 62 Beiträge
Benutzerbeschreibung

Forenbeiträge von Starfight Ingesamt 62 Beiträge

15.11.2017 - 18:51 Uhr

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.

15.11.2017 - 17:01 Uhr

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.

15.11.2017 - 15:55 Uhr

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.

15.11.2017 - 11:13 Uhr

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.

13.11.2017 - 13:38 Uhr

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 ?

13.11.2017 - 11:22 Uhr

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.

13.11.2017 - 11:20 Uhr

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.

12.11.2017 - 16:03 Uhr

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.

12.11.2017 - 15:08 Uhr

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.

11.11.2017 - 15:45 Uhr

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();
        }

15.01.2017 - 23:23 Uhr

Sieht auf jeden Fall schon mal sehr Interessant aus. Danke für den Tipp, ich schau mir das gleich mal genauer an.

15.01.2017 - 15:56 Uhr

Mahlzeit zusammen.
Ich habe sehr viel gesucht, ausprobiert und wieder verworfen, für ein eigentlich banales Problem.
Ich muß ein bestimmtes Programm in einer geringeren Auflösung laufen lassen.
Wenn ein Benutzer also das Programm XYZ startet, soll der Monitor, auf dem das Programm gestartet wird, in eine andere Auflösung wechseln.
Aktuelle Auflösung ist 1920 x 1080, gewünscht wäre z.B. 1680 x 1050.
Ich habe diverse Tools gefunden, die zwar die Auslösung ändern können, aber immer nur für ALLE angeschlossenen Monitore oder für den Hauptmonitor. Ein Programm konnte ich sogar den Namen des Monitors eingeben, für den die Änderung gelten soll. Nützt aber nichts, wenn 3 angeschlossene Monitore den selben Namen haben.

Nun, Windows kann es ja, jedem Monitor eine eigene Auflösung geben, also sollte es doch Programmiertechnisch auch machbar sein.
Am liebsten wäre mir eine Consolenanwendung, die erst die Auslösung ändert, dann das Programm nach startet und nach Beendigung des Programms wieder die vorherige Auflösung einstellt.
Natürlich sollte das ganze auch ohne Neustart des Computers gehen, also ein Registery Hack wäre da wohl eher nicht so angebracht, denke ich.

Tja, wo setzt man da nun an. Eine Funktion im NET Framework scheint es nicht zu geben.

05.01.2016 - 17:50 Uhr

Ich finds eiglich schon erstaunlich, dass eine DataTable überhaupt so viel Information über die Db-Tabelle hat, keine Ahnung, warum nun den Primkey nicht.

Ich finde das keineswegs erstaunlich. Ich meine, mich bei der anfangszeit, als ich Programmieren lernte, erinnern zu können, das da mal was in der Art zu lesen war, wie:

Auf Datenbanken kann man auf zweierlei arten zugreifen.

  1. Man liest jeden Datensatz einzeln, bearbeitet diesen und schreibt ihn wieder zurück.
    Vorteil: Die Datenbank ist immer aktuell
    Nachteil: Hoher traffic

  2. Man liest die gesamte Datenbank ein und bearbeitet diese im Speicher und schreibt die änderungen später zurück.
    Vorteil: weniger traffic
    Nachteil: aktuelle Änderungen werden nicht gleich für alle sichtbar.

Das ist jetzt mal eine FREIE wiedergabe von dem, was ich meine, gelesen zu haben.
Und nach diesem Grundsatz habe ich immer gehandelt. Muß ich nur eine kleinigkeit ändern, mache ich das meist mit direkten Datenbankbefehlen, z.B. UPDATE einer Zeile.
Muß ich größere änderungen vornehmen, wie hier das aktualisieren von ettlichen Zeilen (ca. 50.000), dann lade ich die gesamte Datenbank in den Speicher, aktualisiere in Ruhe und schreibe sie dann zurück.
Letzteres sollte ja einen gewaltigen Geschwindigkeitsvorteil haben, deswegen war ich wohl davon ausgegangen, das ein DataTable auch alle Informationen aus der DatenbankTABELLE besitzt.

Aber irgendwo muss ja eine "InformationsGrenze" sein, sonst könnte man ja auch erwarten, eine Tabelle solle selbst wissen, wie und mit welchen anderen Tabellen sie verknüpft ist

Hmmm, nein, so weit würde ich nicht gehen. Verknüpfungen können bzw. werden während der Programmlaufzeit eventuell geändert. Der PRIMARYKEY wohl eher nicht.

Also du lehnst typisierte Datasets ab, weil "undurchschaubar"?

Ich fand die Handhabung damals sehr kompliziert. Einfaches Beispiel.
Wenn ich in der Datenbank einen Datentyp geändert habe, z.B. von CHAR auf INT, dann kamen die wildesten Fehlermeldungen, wenn man das Dataset nicht auch geändert hat. (Vergesslich ist man schon mal)
Und ich weiß nicht, wie oft ich es hatte, das ich dann zwar im Dataset die Änderung auch vorgenommen hatte, es aber trotzdem nicht klappte und ich erst das Dataset komplett löschen und neu Aufbauen mußte, damit das Teil kappiert, das an der DB was neu ist.

Im Gegenzug dazu das arbeiten mit Datatable ein Kinderspiel.
Connectionstring
Adatper erstellen und konfigurieren.
Datatable erzeugen
Datatable füllen
fertig.

Auch der Zugriff auf ROWS und COLUMNS habe ich beim DataSet immer probleme gehabt.
Beim DataTable ? Simpel. DataTable.ROWS[x].ItemArray[y].value
Oder teilweise auch einfach nur DataTable.ROWS[x]["Columnname"]
Also ich finde das extrem einfach.

Ich finde die im Gegenteil überaus durchschaubar.

Glaube ich Dir. Vielleicht habe ich auch nur die falschen Bücher gehabt. 😄

Und du gibst ja auch einen immensen Haufen an Gestaltungsmöglichkeiten auf

Gestaltungsmöglichkeiten, die ich aber eventuell gar nicht brauche. Mir fällt auf anhieb nichts ein, was ich mit einem DataSet machen kann, aber mit einer DataTable nicht.
Klar, ich kenne DataSets auch nicht so gut, aber eventuell gibts Du mir ja mal ein paar Tips.

hast du mal vom Tut die Sample-Application gedownloaded?
Und das Sample im letzten Artikel der Serie ist noch ein Stück weiter entwickelt (und deshalb auf zusätzliche aufwändige selbstgebastelte Infrastruktur angewiesen, was aber eiglich nicht zählt, denn die Infrastruktur ist ja nur einmal gecodet und fertig).

Nein, habe ich nicht. Ich bin hier gerade mit einem Problem beschäftig, wo mir das Tut auch nicht weiter helfen kann, da die Funktion LOADDATAROW nun mal vom DataTable unterstützt wird und nicht vom DataSet.
Ja, ich weiß, das DataSet hat auch eine Load Funktion, die aber wohl noch komplizierter zu sein scheint, als das von der DataTable.

Aber du sagst, du seist imstande, sowas auch untypisiert hinzuhauen, und würde dir sogar leichter fallen?

Sagte ich, das eine DataTable untypisiert ist ?

Was ist der Vorteil eines typisierten Dataset ?
Man kann mit NAMEN statt Index auf die Werte zugreifen. Also z.B.
DataSet["ArtikelNr"] anstatt DataSet[13]
Nun, das mach teine DataTable von Haus aus.

Weiterer Vorteil: Das typisierte DataSet kennt den Typ jeder Zelle, womit Typkonflikte schon bei der Entwicklung auffallen und nicht erst zur Laufzeit.
Hmmm, macht das DataTable auch.

Und wenn mein Wissen mich nicht ganz alt aussehen lässt, bekommt das DataSet diese Informationen aus der DataTable.
Also wozu soll ich ein DataSet nutzen ? Welchen Vorteil hat es gegenüber der DataTable ?

Aber auch nochmal zurück zu meinem Problem.
Ich habe eine Datenbank mit Artikeln. Aktuell ca. 50.000 Stück. Von meinem Lieferanten bekomme ich nun eine CSV (Excel) Dateil mit den Preisen, Warenbestand usw.
Die will ich jetzt also in die Datenbank einpflegen. Heiß, ich muß jede Zeile in der CSV einlesen, den entsprechenden Datensatz in der Datenbank finden und AKTUALISIEREN oder eben NEU ANLEGEN.
Bisher hatte ich es so gelöst, das ich per SELECT * FROM Waren WHERE ArtikelNr = '123456' gesucht wird. Wird er gefunden, aktualisiere ich den. Wird er nicht gefunden, lege ich einen neu an.
Was natürlich entsprechend Codezeilen voraussetz und das ständige abfragen nach der Artikelnummer auch Zeit benötigt.
Deswegen war mein Gedanke, das über LoadDataRow zu lösen, da dieses ja meine beiden Routinen AKTUALISIEREN oder NEU ANLEGEN in einem erledigt. Gleichzeitig würde die SELECT abfrage entfallen, da ja nur mit der DataTable gearbeitet wird.
Also eine enorme ersparnis an Code und (hoffentlich) auch Zeit.

Nur, das Problem ist ja, das die DataTable den PRIMARYKEY nicht kennt, der für LoadDataRow aber unbedingt vorhanden sein muß.
Setzte ich den PRIMARYKEY in der DataTable auch dahin, wo er in der Datenbank ist, beschwert sich das UPDATE {Adapter.Update(DataTable)}, das da was nicht stimmt.

Alle Beispiele im Internet, die sich mit LoadDataTable befassen, ändern immer nur die DataTable, schreiben diese aber NIEMALS zurück in die Datenbank. WARUM ?????

Sollte jemand noch eine andere möglichkeit kennen, eine masse an Datenzeilen schnell zu bearbeiten und zurück in die Datenbank zu schreiben, immer her damit.

04.01.2016 - 21:25 Uhr

Edit: sorry, sehe jetzt erst, dass du inzwischen ja etwas unternimmst, um der DataTable einen Primkey anzudrehen.
Hab ich so noch nie gemacht - funzt das? (jo, wird wohl)

Nein, funktioniert nicht, wie man an der Fehlermeldung sehen kann.
Mein Fazit: LoadDataRow ist nur brauchbar, wenn man in die DataTable was machen will und dieses NIEMALS zurück in die Datenbank speichern will oder es wird so Aufwendig, das ich lieber zwei eigene Routinen schreibe, die das ganze selbst erledigen, ohne LoadDataRow.
Hatte nur gehoft, das es mit LoadDataRow schneller und auch einfacher geht.

ich lass mir meine typDatasets immer von VS-Assistenten generieren

Hatte ich früher auch mal gemacht, war mir aber später zu unflexibel und zu wenig durchschaubar, was da genau abgeht.

bzw. ich hab mir ein Tool gebastelt, was den Vorgang umdreht: Aus meinem typDataset generiert es die Datenbank.

Hilft aber wenig, wenn man mit bereits vorhandenen Datenbanken arbeiten muß. 😄

Und ist halt typisiert - mit den weitreichenden Folgen für die ganze Anwendungs-Entwicklung - gucks dir wirklich mal an.

Ehrlich gesagt, lieber nicht. Ich habe früher auch mit DataSets gearbeitet, aber bin auch ständig und überall auf Probleme gestoßen, die mehr oder weniger schlecht zu lösen waren.
Seit ich nur noch mit Datatables arbeite, ist das um längen einfacher geworden und ich sehe noch keine Probleme, auch mit großen Datenbanken klar zu kommen.
Das LoadDataRow Problem ist ärgerlich, aber wohl in meinen Augen eher ein MS Problem. Warum wird den eine DataTable nicht von Haus aus eine 100% kopie der Datenbank ?
Würde ja offensichtlich einige Probleme von vornherein ausschließen.

04.01.2016 - 15:24 Uhr

Ähm, sollte ein DataTable nicht eine exakte Kopie der Tabelle aus der Datenbank sein ? Also INKL. Primärschlüssel ?

Offensichtlich hast du den Primkey in der Datenbank festgelegt, aber deine DataTable weiß ja nix davon. Für die DT ist das eine Spalte wie jede andere.

Heißt, ich muß erst noch von der Datenbank erfragen, welche Spalte den Primärschlüssel hat und der DataTable dann extra noch mitteilen ?
Hmmm, ich habe jetzt mal per Hand den Primärschlüssel auf die entsprechende Spalte gesetzt und ja, dann geht LoadDataRow tatsächlich korrekt.

generell täte ich von untypisierten Datasets abraten. Verwende typisierte Datasets oder EntityFramework, aber kein untyp Dataset.

Du redest von DataSET, ich von DataTABLE. Ich denke, das ist ein deutlichen Unterschied.
Aber nach obiger Erfahrung bin ich nun verunsichert, das eine gefüllte DataTable tatsächlich von jeder Spalte weiß, welchen Datentyp diese haben sollte.
Andererseits, wenn ich ein DataGrifview an die DataTable binde, weiß das DataGridview sehr wohl, was angezeigt werden soll, also ein Datentyp BIT wird dann auch als Checkbox angezeigt. Somit denke ich doch, das diese Info in der DataTable bereits vorhanden sein muß bzw. beim FILL mit übertragen wurde. Warum dann also nicht auch der Primärschlüssel ?

Das ist aber nur das eine. TypDatasets bieten darüberhinaus auch die Möglichkeit der Databinding-getriebenen Oberflächen-Entwicklung - sagt dir das was?

Datenbindung sagt mir durchaus etwas. Oft genug Textboxen, Comboboxen oder DataGridviews an DataTables gebunden. Hat immer prima geklapt, ohne das ich am Datatable nachträglich irgendwas ändern mußte.

Tja, leider funktioniert dann aber das Update nicht mehr, weil nun die DataTable nicht mehr mit der Datenbank übereinstimmt.
Es kommt dann zur Fehlermeldung

Zusätzliche Informationen: Dynamische SQL-Generierung wird für einen SelectCommand, der keine Basistabelleninformationen zurückgibt, nicht unterstützt.

Hier mal die änderungen, die ich nun eingefügt habe.

Hiermit frage ich in der Datenbanktabelle ab, welche Column den PRIMARYKEY hat.

adapterSQL.SelectCommand.CommandText = "SELECT column_name FROM information_schema.key_column_usage WHERE OBJECTPROPERTY(OBJECT_ID(constraint_name), 'IsPrimaryKey') = 1 AND table_name = 'Waren'";
DataTable schema = new DataTable();
adapterSQL.Fill(schema);

Hiermit setzte ich dann in der bereits gefüllten Datatable den PRIMARYKEY

DataColumn[] keys = new DataColumn[1];
keys[0] = DT.Columns[schema.Rows[0].ItemArray[0].ToString()];
DT.PrimaryKey = keys;

Hier wird dann das OBJECT[] mit den entsprechenden Werten gefüllt und mit LOADDATAROW entweder in der DataTable ST eine neue Zeile eingefügt, wenn die Artikelnummer (PRIMAYKEY) noch nicht vorhanden ist, ODER eben, wenn die ROW doch schon vorhanden ist, aktualisiert.


object[] newRow = new object[15];
newRow[0] = Convert.ToInt32(ArtikelCSV[0]);
newRow[1] = Convert.ToInt32(ArtikelCSV[1]);
newRow[2] = ArtikelCSV[2];
...
DT.BeginLoadData();
DT.LoadDataRow (newRow, false);

DT.EndLoadData();

Ein abschließendes

adapterSQL.Update(DT);

schreibt die Daten dann auch tatsächlich in die Datenbank.

Bleibt nu zu sagen, das ich es bessern finden würde, wenn ein DataTable tatsächlich eine 100% kopie der Datenbanktabelle wäre.

04.01.2016 - 11:06 Uhr

Na wie legt man nen Primarykey schon fest.

Entweder SQLServer Managment Studio, wählt die Tabelle aus, ENTWERFEN, Spalte Artikelnummer, rechtsklick und wählt Primärschlüssel.

Oder halt mit "ArtikelNr integer PRIMARY KEY," beim erstellen der Datenbank.

Aber ich denke nicht, dass das hier mit dem Problem zu tun hat, weil, wenn ich ja die DT in die Datenbank zurückspeichern will, hat er ja ZWEIMAL die selbe Artikelnummer drin und dann beschwert sich das System auch wegen Primärschlüssel verletzung. Sagt doch eigentlich, das der Schlüssel gesetzt ist und funktioniert.
Und nein, weitere Primärschlüssel gibt es nicht.

04.01.2016 - 00:47 Uhr

verwendetes Datenbanksystem: SQLExpress

Wenn ich LoadDataRow richtig verstanden habe, sucht es in einer gefüllten DataTable in einem Primärschlüssel nach einem Wert, der ich im Object[] übergebe und wenn gefunden, wird diese Zeile aktualisiert. Wird der Wert nicht gefunden, wird eine neue Zeile angelegt.

Das Problem bei mir, es wird IMMER eine neue Zeile angelegt, obwohl der Wert definitiv vorhanden ist.

Gegeben ist eine Datenbank SQLExpress mit einer Tabelle, wo eine Spalte als Primärschlüssel definiert ist. Da stehen Artikelnummern drin. Ich habe da eine Zeile, die hat die Artikelnummer 119508.
Nun erstelle ich ein Object[] und fülle es.

object[] newRow = new object[15];
newRow[0] = Convert.ToInt32(ArtikelCSV[0]);
newRow[1] = Convert.ToInt32(ArtikelCSV[1]);
newRow[2] = ArtikelCSV[2];
...

Dann kommt folgendes:

DT.BeginLoadData();
DT.LoadDataRow (newRow, false);
DT.EndLoadData();

Die Werte aus dem Object[] werden als NEUE Zeile in DT übernommen, anstatt die vorhandene Zeile mit den neuen Werten zu überschreiben.
Ob ich bei LoadDataRow ein FALSE oder TRUE angebe, ist an dieser Stelle auch uninteresant. Das wird erst interessant, wenn dann das UPDATE kommt, um die Werte zurück in die Datenbank zu schreiben. Da kommt es dann bei FALSE natürlich zu einem Fehler, weil der Primärschlüssel verletzt wird.

Aber was habe ich da an LoadDataRow nun falsch verstanden oder falsch programmiert ?

23.12.2015 - 11:43 Uhr

SQL? Welches?
Beim MSSQL Server kannst Du z.B. mit + arbeiten.

Sorry, vergessen. Ja MSSQL

Allerdings ist das Abfragen der einzelnen Spalten + das Aufbereiten dieser Daten bevor du sie im Control anzeigst, die deutlich bessere Variante.

Ähm, mit + ?
[Ausprobier]
Cool, klappt. Herzlichen Dank

@Taipi88
Ich zitiere mal

So weit, so gut. Nur, wie bekomme ich das nun mit SQL hin ?

Sorry, das ich SQL nicht genauer definiert hatte.

@T-Virus
Wenn ich die Daten nachträglich aufbereiten muß, bedeutet das wieder eine zusätzliche schleife. Wozu, wenn man es gleich in der Abfrage mit erledigen kann ?
Und wie mein Satz "Die formatierung wäre durchaus wichtig, da die Daten direkt aus der Datatable in eine ComboBox eingelesen und dort zur Auswahl bereitgestellt werden." schon andeutet, nur zur Auswahl benötigt und sonst nicht weiter verwendet.

Aber, wie es scheint, habe ich doch keine andere wahl, da die Option mit dem "+" nicht mit INTEGER Werten klar kommt und eine Typumwandlung in der SELECT wohl nicht möglich ist.

Danke an alle für die Hilfe.

22.12.2015 - 22:55 Uhr

verwendetes Datenbanksystem: SQLBase

Ich habe hier ein Programm, das mit SQLBase arbeitet. Dort wird eine Anfrage an das Datenbanksystem geschickt, die wie folgt aussieht:

Select distinct NAME1||'  '||NAME2||' KD-Nr.: '||KUNDEN.KDNR||'  '||KUNDEN.INFO from KUNDEN where KENNUNG=:1 and MDNR=:2 order by NAME1

Das Ergebnis ist etwas in der Art wie:


Kundenvorname Kundennachname KD-Nr.: 123456 Kundeninfo

So weit, so gut.
Nur, wie bekomme ich das nun mit SQL hin ?
die "||" Zeichen scheint SQL nicht zu kennen. In CSharp werden diese ja als ODER genutzt, aber ein ODER macht in der Abfrage keinen Sinn und auch das Ergebnis hat nichts mit einem ODER zu tun.
Es sieht mir eher so aus, als wenn man damit die Ausgabe gleich formatieren kann.
Es wird ja der VORNAME ausgegeben, dann ein Leerzeichen, dann der NAME, dann der Text "KD-Nr.:" gefolgt von der KUNDENNUMMER und der KUNDENINFO.
Klar, ein SELECT NAME1,NAME2,KUNDEN.KDNR, KUNDEN.INFO ..... würde mir die selben Daten liefern, aber nicht bereits formatiert.
Die formatierung wäre durchaus wichtig, da die Daten direkt aus der Datatable in eine ComboBox eingelesen und dort zur Auswahl bereitgestellt werden.

Jemand eine Idee, wie man das hinbekommen kann ?

01.05.2015 - 01:37 Uhr

PS: Um Standardwerte in eine neue Zeile zu geben, gibt es das
>

Ok, klingt zwar gut, führt aber zu folgendem Fehler:
Zusätzliche Informationen: Der Vorgang ist ungültig, da er einen Wiedereintrittsaufruf an die SetCurrentCellAddressCore-Funktion zur Folge hat.
wenn ich versuche CurrentCell zu setzen.

Gibt es den keine alternative zu diesem Currentcell ?

Was das verzögern des wechsel des aktuellen Feldes angeht, weiß ich nicht genau, was Du damit bezwecken willst.
Ich muß nun mal irgendwie erkennen, das eine neue ROW eingefügt wurde, die dann mit Standartwerten belegt wird. Soweit ja auch kein Problem, das klappt ja.
Das dann eine bestimmte Zelle den Eingabefocus erhalten soll, da liegt das Problem.
So wie ich das sehe stört sich das System daran, das ich innerhalb einer Ereignissroutine eine Funktion aufrufe, die exakt dieses Ereigniss wieder aufrufen würde.
Da hilft mir irgendeine Verzögerung doch nichts.

27.04.2015 - 14:42 Uhr

Nein, das hilft leider nicht weiter, da ein abschalten des Ereignis mittels

                    dataGridView2.RowEnter -= dataGridView2_RowEnter;
                    dataGridView2.CurrentCell = dataGridView2.Rows[dataGridView2.Rows.Count - 1].Cells["Zusage"];
                    dataGridView2.RowEnter += dataGridView2_RowEnter;

dennoch zum Fehler führt:> Fehlermeldung:

Zusätzliche Informationen: Der Vorgang ist ungültig, da er einen Wiedereintrittsaufruf an die SetCurrentCellAddressCore-Funktion zur Folge hat.

27.04.2015 - 14:06 Uhr

Puh, ich brauch mal wieder jemanden, der mir das Brett vorm Kopf wegnehmen kann.

Ich habe ein Datagridview, in dem ich Eingaben machen will. Wenn eine neue Zeile hinzukommt, weil man halt mehrere Zeilen eingeben will, sollen gewisse Zellen mit Werten vorbelegt werden. Das realisiere ich über das RowEnter Ereignis.
Soweit, so gut.

Nun würde ich aber auch gerne beim eintreten des Ereignis einer bestimmte Zelle den Eingabefocus geben.
Mittels

DataGridView.Currentcell = DataGridView.Rows[e.RowIndex].Cells["Zusage"];

geht es nicht, weil ich dann einen Ausnahmefehler bekomme, weil dieser Aufruf wieder das Ereignis "RowEnter" auslösen würde und ich so in einer Endlosschleife lande.

Frage ist nun: Wie kann ich die Zelle mit einem Eingabefocus versehen, ohne CurrentCell nutzen zu müssen ?

06.04.2014 - 14:35 Uhr

Ich habe eine Form mir mehreren Controlls. Unter anderem eine Textbox und einen Button.
Der Button ist mittels BUTTON.ENABLED = false erst mal deaktiviert.
Er soll nur aktiviert werden, wenn eine bestimmte textbox den Focus hat.

Ich habe also das Ereignis Textbox.Fokus.Enter und Textbox.Fokus.Leave auf zwei Routinen geleitet, die den Button mittels Button.Enabled = true bzw. Button.Enabled = false ein bzw. aus schalten.

So weit, so gut.
Problem daran ist, wenn die textbox den Fokus hat und ich dann den Button anklicke, dann wird zuerst das Ereignis Textbox.Fokus.Leave ausgelöst. In der entsprechenden Routine wird dann ja der Button deaktiviert und damit erreiche ich das Ereignis Button.Click nicht mehr.

Sinn und Zweck ist es, das über den Button ein zusätzliches Formular aufgerufen wird, in dem man etwas auswählen kann und dieses dann in der textbox angezeigt wird. Aber, diese Auswahl darf eben auch nur möglich sein, wenn die entsprechende Textbox den Fokus hat.

Jemand eine Idee, ob und wie man die Reihenfolge der Ereignisse ändern kann ?

22.03.2014 - 13:45 Uhr

Ich hatte zwei SUO Dateien, warum auch immer.
Projektname.suo
Projektname.v11.suo

Ich habe dann beide mal in ein TEMP Verzeichnis verschoben und das Projekt neu geladen und hurra, diese nervige Meldung ist weg.
Vielen herzlichen Dank.

22.03.2014 - 11:51 Uhr

Ich habe da seit kurzem ein nerviges Problem.
Ich arbeite an einem größeren Programm und vor wenigen Wochen erschien beim laden des Projekts die Fehlermeldung "Ein oder mehrere Haltepunkt(e) können nicht geladen werden". Dies erscheitn zweimal. Das Projekt wird aber normal geladen und ich kann auch Debuggen.
Der Menüpunkt Debuggen->Alle Haltepunkte löschen ist aber nicht anwählbar.

Eien Suche in Google brachte auch keine wirklichen Treffer zu dem Problem.

Eine Liste alle Haltepunkte habe ich aber auch noch nicht gesehen.

Kennst jemand eine Möglichkeit, dieses nervige Problem zu beseitigen ?

09.03.2014 - 14:20 Uhr

Tja, das es schwerer als nötig war, kann man so oder so sehen. Nur, wenn man nicht auf den richtigen Gedanken kommt, was soll man machen, außer hier zu fragen.
Durch einen Beitrag in einem Buch bin ich mittlerweile auch darauf gekommen, das man die Daten mittels eines DATAROWVIEW an die andere Form übergibt.
Ich stand halt bisher vor dem Problem, das ich in Form ein das DataSet mit allen Daten hatte, aber nicht nur den Teil, der bearbeitet werden soll.
Das Datagridview auslesen und die Werte einzeln übergeben erschien mir als viel zu aufwendig.

Das mit dem DataRowView funktioniert jetzt zwar, ist aber leider in teilen auch nicht ganz so komfortabel wie die Lösung mit den Databindungs, aber in den sauren Apfel muß ich wohl beissen.

Vielen Dank an alle, die mir die Augen geöffnet haben.

07.03.2014 - 12:25 Uhr

Erst mal Danke für den Hinweis, auf diese Simple Lösung bin ich irgendwie nicht gekommen, obwohl ich schon mit Kommunikation zwischen zwei Formen programmiert habe. 😄
Aber....

Wenn ich in Form1 per "SELECT * FROM Kunden WHERE ...." eine DataTable mit dem einen Datensatz fülle und den an FORM2 übergebe
Kunden_NEU KDNeu = new Kunden_NEU();
Kunden_NEU.DTKunden = dt;
KDNeu.ShowDialog();

und dann in Form1 mittels
INT a = DAKunden.Update(dt);
die Daten updaten will, werden diese nicht in die Datenbank geschrieben. a hat den Wert null. in dt stehen aber die neuen Werte drin.

Ich kann ja auch schlecht die gesamte Tabelle als Dataset übergeben, dann müßte ich in Form2 erst wieder den zu ändernden Datensatz raussuchen, ein neues Dataset füllen. Ich sehe schon kommen, dass das dann auch wieder nicht in die Datenbank geschrieben wird oder die änderungen danach wieder nicht im Datagrifview angezeigt werden.

Von Form2 aus direkt auf die Datatable der Form1 zugreifen geht ja auch nicht, weil eine Select Abfrage mit einem Datensatz als Rückgabe dann ja auch das Datagrifview in Form1 beeinträchtigt und das soll es so ja nicht.

07.03.2014 - 08:57 Uhr

Datenbanksystem: SQL Express 2012

Folgender Fall. Ich habe eien Form mit einem Datagridview, das mir eine Kundenliste anzeigt.
Will man einen EIntrag editieren, öffnet sich eine neue Form mit entsprechenden Eingabefeldern.
Ich übergebe also von der ersten Form die Kundennummer an die zweite Form, rufe in einem Dataset/Datatable diesen einen Datensatz auf und habe die entsprechenden Textboxen, Comboboxen usw. per Databinding an das Dataset/Datatable gebunden. (Dataset/Datatable heißt, ich habe beides versucht)
Sind die änderungen gemacht, klickt man auf OK und mittels

                BindingContext[Kunden].EndCurrentEdit();
                adapterSQL.Update(Kunden);

werden die Daten in der Datenbank aktualisiert. Das klappt aoweit auch bestens.
Dann schließt sich die Form2 und wir sind wieder auf der Form mit dem Datagridview. Nur werden hier dann noch die alten Daten angezeigt.

Ich möchte nun ungern alle Datensätze mit einem adapterSQL.Fill komplett neu laden.

Ich hatte auch schon versucht, in der ersten Form ein BindingSource an das Dataset zu hängen.

BindingSource BS = new Bindingsource();
adapterSQL.Fill(Dataset, "kunden");
BS.Datatsource = Dataset;

...
...
und wenn ich dann die zweite Form wieder schließe, kommt in Form1 noch ein

BS.EndEdit();
dataGridView1.Refresh();

Aber es werden immer noch die alten, unveränderten Daten angezeigt.

Was kann ich tun, außer das Dataset komplett neu zu laden ?

06.03.2014 - 16:45 Uhr

Falls Du immer noch an dem Problem hängst, ich habs gerade nach langem suchen lösen können.

Im Internet fand ich folgenden Hinweis: this.BindingContext[this.dataSet1, "DeineTabelle"].EndCurrentEdit()

Dieses unmittelbar vor dem Adapter.Update und die änderungen werden übernommen.

06.03.2014 - 15:59 Uhr

Das hat funktioniert akunz.
Ich danke euch vielmals.

06.03.2014 - 11:40 Uhr

Ok, den Dienst Aufgabenplanung habe ich zwar, kann aber nichts daran ändern.
Betriebssystem ist Windows 8.1 und ja, Administrator bin ich auch. Auch habe ich versucht, die Diensteverwaltung mit Administratorrechten zu starten, aber ich kann den Dienst weder stoppen, noch via Eigenschaften irgendetwas daran verändern.

06.03.2014 - 07:32 Uhr

Ich habe ein Programm geschrieben, das jeden Tag einmal ausgeführt werden soll. Dazu habe ich einen Eintrag im Windows Aufgabenplaner erstellt.
Das Programm wird auch gestartet und arbeitet, das sehe ich an der LOG Datei, die es erstellt. Aber, das Programmfenster wird mir nicht angezeigt.
Bei Programmstart wird sofort ein this.Show(); ausgeführt, aber das hilft wohl nicht.

Wie bekomme ich es hin, dass das Programm startet und auch zu sehen ist ?
Muß ich in meinem Code irgendetwas hinzufügen oder liegt das Problem eher am Aufgabenplaner selbst.

17.04.2009 - 09:30 Uhr

Nein, der andere Rechner war eine 32bit Maschine.
Und ja, auf x86 kompiliert und es klappt.
Au man. Auf sowas muß man kommen.
Vielen herzlichen Dank.

17.04.2009 - 01:00 Uhr

Puh, ich hab da ein riesen Problem.
Betriebssystem ist Vista 64 bit. Programmiere in C# und möchte einfach nur auf eine MS Access Datenbankdatei zugreifen.
Der einfache weg:
Menü Daten -> neue Datenquelle hinzufügen -> Datenbank -> Neue Verbindung -> Durchsuchen und die Datenbankdatei angeben.
Dann wähle ich alle Tabellen aus und sage "fertig stellen"

Die Datenbank erscheint dann auch links. Ich ziehe die Tabellen dann auf meine Form und es wird ein DataGridView, BindingNavigator, DataSet. Wird alles automatisch erstellt.

Nun starte ich mein Programm und im DataGridView werden mir nur die Header angezeigt, aber keine Daten.
Gehe ich aber auf den TableAdapter und wähle Datenvorschau, werden mir die Daten angezeigt.
Nehme ich genau dieses Programm und kopiere es auf einen anderen Rechner, läuft alles einwandfrei.

Es sieht für mich momentan so aus, als wenn ich aus irgendeinem Grund keinerlei Daten aus einer Access Datenbank lesen kann.

Arbeite ich das kurze Programm im Einzelschritt ab, kommt diese Zeile:
this.tabelle1TableAdapter.Fill(this.datenbank1DataSet.Tabelle1);

Sobald ich die abarbeite, springt er raus. Es scheint hier also ein Fehler aufzutreten. Nur zeigt er mir nichts an.

Übrigens kann ich mit einem anderen Programm durchaus noch Daten aus einer SQLExpress Datenbank auslesen. Das Problem besteht offensichtlich nur bei Access Datenbanken.

NET Framework 3.5 hatte ich schon mal komplett deinstalliert, neu gestartet und neu installiert. Leider ohne erfolg.

Kurz gesagt, ihr seid meine letzte Hoffnung, bevor ich den Rechner komplett neu aufsetzen muss, wozu ich aber eigentlich überhaupt keine Lust verspüre.

07.01.2008 - 14:09 Uhr

Cyron, ich glaub, Du hast mein Problem nicht verstanden oder ich deinen Beispielcode nicht. 🙂
Was soll z.B. diese Zeile
AdresseNeu aneu = new AdresseNeu();
bewirken ?

Versuch ich es nochmals zu verdeutlichen.

Wir nehmen mal 4 Struct's. (Im fertigen Programm werden es deutlich mehr)
Struct1
Struct2
Struct3
Struct4

Jede Structure halt mit diversen Variablen versehen.
Nun muß ich z.B. einen Datensatz schreiben, der aus
Struct1 + Struct3
zusammengesetzt wird
Oder einen Datensatz, der aus
Stuct2 + Struct3 + Struct4
zusammengesetzt ist.

Also am liebesten wäre mir ein
StructNEU = Struct1 + Struct3
StructNEU.Struct1.irgendwas = xyz
StructNEU.Struct3.irgendwann = abc

Und dann ein Streamwriter.write(StrunctNEU);

Das wäre der Idealfall.

29.12.2007 - 15:46 Uhr

Feste länge deswegen, weil mir der Dateiaufbau extern vorgegeben wird.
Alle Felder haben eine feste länge, leerstellen müssen mit 0 aufgefüllt werden.

Bei deiner Lösung fehlt das Struct in einer Struct.
Es geht ja eben genau darum, das ich eine Structure ANSCHRIFT bekomme, die sich aus der Structure NAME und ADRESSE zusammensetzt.

Im fertigen Programm wird das noch was aufwendiger, das soll nur als Beispiel dienen.
Stell es Dir einfach so vor, das ich eine Structure ANSCHRIFT habe. Dazu sollen nun weitere Daten in eine Datei geschrieben werden, die auch alle einen festen Aufbau haben. z.B: ne Bestellung oder ne Reklamation.
Wobei dann Bestellung und Reklamation auch wieder in Structuren angelegt sein sollen.

Dann eben eine neue Structure erstellen, in der dann z.B.
Struct Datensatz
{
struct Anschrift;
struct Bestellung;
}

oder eben
Struct Datensatz
{
struct Anschrift;
struct Reklamation;
}
vorkommen.

29.12.2007 - 14:56 Uhr

Mahlzeit zusammen
Ich bräuchte etwas in der Art:

Struct test1
{
   string a1;
   string a2;
   string a3;
}

Struct test2
{
   string b1;
   string b2;
}

struct test3
{
   struct test1;
   struct test2;
}

Sinn ist es, das ich die einzelnen Structuren in einem Programm befüllen kann und dann aber z.B. mit StreamWriter nur struct test3 in eine Datei schreiben kann.
Struct test1 und test2 sollen in verschiedenen anderen Structuren immer wieder verwendet werden können.
Also z.B. in Struct test1 wir dnur Name, Vorname festgehalten, in Struct test2 die Adresse. Und in struct test3 wird dann quasi beides zusammengeführt.

Das will bei mir aber leider nicht so richtig klappen. Jemand nen Tip ?

Dazu kommt noch das Problem, das ich Strings mit fixer länge brauche.
Wenn ich aber FIXED verwende, kommt die Fehlermeldung "Zeiger und Buffer fester größe können nur in einem unsicheren Kontext verwendet werden"

 public struct test
        {
            public fixed String x[5];
            public fixed String y[5];
        }

Schreibe ich es so,
        unsafe public struct test
        {
            public fixed String x[5];
            public fixed String y[5];
        }

jammert er wegen dem String rum, das er dann nicht mag.
Also habe ich es mit
        unsafe public struct test
        {
            public fixed Char x[5];
            public fixed Char y[5];
        }

gemacht. Im Programm schreibe ich dann
Variablen.test aa;
aa.x[0] = "test";
Da jammert er, weil er String nicht in Char konvertieren mag.

Irgendwie fällt mir der richtige Lösungsansatz bzw. alternative Lösungen nicht ein.

12.04.2007 - 11:24 Uhr

Also gleich nochmal den Hinweis. Ich will mein Programm nicht mit Adminrechten Installieren, weil das eventuell auch mal an andere weitergegeben wird und wenn man denen sagt "Mußt Du mit Adminrechten Installieren" hinterläst das immer nen bitteren beigeschmack.

Zur Entwicklungsumgebung. Ja, ich bin als Admin angemeldet.
Ob der Account rechte zum Zeit setzen hat. Hmmm, sollte er wohl, sonst könnte ich auch nicht über die Uhrzeit im Tray die Uhrzeit verändern.

Nein, es läuft sonst eigentlich nichts, was auf die Systemuhr verändernd einwirkt, außer der Windows eigene Service.

11.04.2007 - 10:44 Uhr

Hmmm, und was sollen mir die Adminrechte bei der Installation helfen ?
Nicht mal in der Entwicklungsumgebung klappt das mit SetSystemTime.

03.04.2007 - 09:53 Uhr

Ich habe den Code von sarabande mit hilfe einiger Beiträge aus dem Internet nun endlich so weit, das zumindest alle API Aufrufe ein TRUE zurück liefern.

Einzig die SetSystemTime liefert mir blöderweise nur ein FALSE und wenn ich mit
int apiError = Marshal.GetLastWin32Error();
abfrage warum, heißt es wieder nur, das ich keien Privileien hätte.

Könnte ich bitte nochmal jemand den Code ansehen und mir sagen, was ich da noch falsch mache.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace Systemzeit
{
    public partial class Form1 : Form
    {
        [StructLayout(LayoutKind.Sequential)]
        private struct SYSTEMTIME
        {
            public short uYear;
            public short uMonth;
            public short uDayOfWeek;
            public short uDay;
            public short uHour;
            public short uMinute;
            public short uSecond;
            public short uMilliseconds;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct LUID
        {
            public int LowPart;
            public int HighPart;
        }//end struct

        [StructLayout(LayoutKind.Sequential)]
        public struct TOKEN_PRIVILEGES
        {
            public LUID Luid;
            public int Attributes;
            public int PrivilegeCount;
        }//end struct


        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool OpenProcessToken(IntPtr hProcess, int tokenAccess, ref IntPtr token);

        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool LookupPrivilegeValue(IntPtr lpSystemName, string lpname, [MarshalAs(UnmanagedType.Struct)] ref LUID lpLuid);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool SetSystemTime(ref SYSTEMTIME lpSystemTime);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool GetSystemTime(ref SYSTEMTIME lpSystemTime);

        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, int BufferLength, IntPtr PreviousState, IntPtr ReturnLength);

        [DllImport("kernel32.dll", EntryPoint = "CloseHandle")]
        static extern bool CloseHandle(IntPtr handle);

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            const int TOKEN_ADJUST_PRIVILEGES = 0x0020;
            const int TOKEN_QUERY = 0x0008;
            const int SE_PRIVILEGE_ENABLED = 0x0002;
            bool Res = false;
            //IntPtr hToken = IntPtr.Zero;
            SYSTEMTIME st = new SYSTEMTIME();
            
            GetSystemTime(ref st);

            //GetSystemTime hat keinen Res, ergo kein ProtocolMessage
            Process hProcess = Process.GetCurrentProcess();
            IntPtr hToken = IntPtr.Zero;
            
            //Res = OpenProcessToken(hProcess.Handle, TOKEN_ADJUST_PRIVILEGES, ref hToken);
            Res = OpenProcessToken(hProcess.Handle, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref hToken);
            if (Res == false)
            {
                int apiError = Marshal.GetLastWin32Error();
                StringBuilder errorMessage = new StringBuilder(1024);
                throw new Exception(errorMessage.ToString());
            }

            LUID luid = new LUID();
            TOKEN_PRIVILEGES tp = new TOKEN_PRIVILEGES();
            tp.PrivilegeCount = 1;
            tp.Attributes = SE_PRIVILEGE_ENABLED;

            //Res = LookupPrivilegeValue(IntPtr.Zero, "SeSystemtimePrivilege", ref luid);
            Res = LookupPrivilegeValue(IntPtr.Zero, "SeSystemtimePrivilege", ref luid);

            tp.PrivilegeCount = 1;
            tp.Attributes = SE_PRIVILEGE_ENABLED;
            

            Res = AdjustTokenPrivileges(hToken, false, ref tp, 0, IntPtr.Zero,IntPtr.Zero);

            //Hier stelle ich die Uhr um
            st.uHour = Convert.ToInt16(st.uHour - 1);
            Res = SetSystemTime(ref st);
            if (Res == false)
            {
                int apiError = Marshal.GetLastWin32Error();
                StringBuilder errorMessage = new StringBuilder(1024);
                throw new Exception(errorMessage.ToString());
            }

            Res = CloseHandle(hToken);
        }
    }
}

//edit: c# code tags ergänzt!!!
(siehe Wie poste ich richtig? punkt 6)

28.03.2007 - 16:24 Uhr

Da irrst Du aber gewaltig. Ich habe keineswegs von einem Compilerfehler geredet. Schau Dir die entsprechende Nachricht nochmal genau an. Das genaue Gegenteil habe ich gesagt.
"So, ich habe den Code nun mal soweit umgeschrieben, das zumindest der Compiler keine Fehlermeldungen merh ausspuckt."

Der Code ist soweit, das es ohne Fehlermeldung kompiliert wird. Nur eben,das die angesprochene Funktion FALSE statt TRUE liefert.

28.03.2007 - 09:32 Uhr

Mein lieber sarabande.
Wo habe ich geschrieben, das es ein Compiler Fehler ist ?

Warum ich dein Win32 Class auseinander genommen habe ?
Weil es sonst nicht funktionierte.

26.03.2007 - 20:24 Uhr

[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool OpenProcessToken(Process hProcess,
inttokenAccess, ref IntPtr token);

const int TOKEN_ADJUST_PRIVILEGES = 0x0020;
const int TOKEN_QUERY = 0x0008;
bool Res = false;
Process hProcess = Process.GetCurrentProcess();
IntPtr hToken = IntPtr.Zero;

Res = OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref hToken);

Res hat danach FALSE.

26.03.2007 - 09:52 Uhr

So, ich habe den Code nun mal soweit umgeschrieben, das zumindest der Compiler keine Fehlermeldungen merh ausspuckt.
Allerdings bekomme ich von der OpenProcessToken ein FALSE zurück und ich kann nicht nachvollziehen, warum.
Könntest Du dir das mal bitte ansehen sarabande ?

26.03.2007 - 09:09 Uhr

@ikaros
Hast Du alle Nachrichten durchgelesen ?
Ich will nicht, das mein Programm Adinrechte bekommt bzw. erfordert.
Ich persönlich wäre bei einem Tool, was ich mir aus dem Internet runterlade und das nach Adminrechten schreit, auch sehr Vorsichtig bzw. würde es erst gar nicht nutzen.

@sarabande
Danke für deine Ausführliche Hilfe, aber ich bekomme nicht mal den original c++ Code bei mir ans laufen.
Ich hätte nicht gedacht, das es so kompliziert wird, nur mal eben die Systemuhr umzustellen.

24.03.2007 - 21:02 Uhr

Puh, das hagelt Fehlermeldungen.
Das ist alles mögliche, aber kein lauffähiger C# Code.

Win32.OpenProcessToken
kennt er gar nicht.

LUID luid = new LUID();
Keine Ahnung, was LUID ist.

TOKEN_PRIVILEGES tp = new TOKEN_PRIVILEGES();
ebenfalls unbekannt.

LookupPrivilegeValue
Auch unbekannt.

Puh, ob ich daraus nochmal was lauffähiges bekomme.

24.03.2007 - 18:35 Uhr

Ja, da gibt es erhebliche Probleme.
Ich habe zwar vor zig Jahren mal C gelernt, aber die Unterschiede zu C# sind doch erheblich.

AdjustTokenPrivileges
Sowas gibt es in C# gar nicht. Geht offensichtlich nur über DLL Aufrufe.
Und dann das umwandeln aller Variablen in C#.

TOKEN_PRIVILEGES tp;
Kennt C# auch net.

Gibts den keinen Beispielcode direkt für C# ?

24.03.2007 - 09:00 Uhr

Ja sheitman. Antworten wie die deien sind es, die einen immer wieder Aufbauen.
Ich finde es auch gut, das nicht jedes x-beliebige Programm an meiner Systemuhr rumbastelt. Und ? Darf ich mir deswegen nicht trotzdem eines schreiben, was es trotzdem tut ?

Genau das ist es ja, was ich vermeiden will, das mein Programm, auch nur kurzfristig, Adminrechte bekommt. Nur weil man mal eben die Systemzeit ändern will muß man einem Programm doch nicht gleich vollzugriff auf alles im Computer geben. So blöd kann nicht mal Microsoft sein.
Obwohl, hmm, wenn ich mal so drüber Nachdenke. 🙂

@sarabande
Danke, ich werde mir das sofort mal ansehen und mal gucken, ob ich den Code nach C# portieren kann bzw. mir fehlende Informationen daraus ableiten kann.

23.03.2007 - 15:53 Uhr

http://msdn2.microsoft.com/en-us/library/aa375202.aspx

Grob gesagt, ich habe keinen blassen Schimmer, was die von mir wollen. 😦

Die Optionen, die bei "Running with Special Privileges." angeboten werden, sind Inakzeptabel. Weder will ich den User bitten, das Programm mti Admin Status zu starten, noch will ich mitten im Programm die Admin Datenabfragen.
Wenn mich ein Programm mitten drin nach dem Administratorpassword fragen würde, würde ich es gleich Löschen.

Ich sehe ja ein, das das verstellen der Systemzeit nich tvon jedem X-beliebigen Programm gemacht werden darf, aber warum bitte nich einfach ne Option:
Message Fenster auf: Darf das Programm die Systemezit ändern: Ja / Nein
und gut ist.
Aber ich weiß nicht, wie ich dem Programm nur für diesen kurzen Augenblick die entsprechenden Rechte geben könnte.
Außer eben mit AdjustTokenPrivileges, aber das ist ein wenig zu kompliziert für mich.

22.03.2007 - 20:08 Uhr

@Borg
GetLastError gibt zurück, das Rechte fehler.

@sarabande
Stell Dir vor. Habe ich gelesen.
Und ? Wie geht man dann weiter vor ?
Beispiele, wie man SE_SYSTEMTIME_NAME habe ich keine gefunden oder funktionieren bei mir nicht.