vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Erstellen von dynamischen Kontextmen?s - wann immer Sie sie brauchen!  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück

 Sie sind aktuell nicht angemeldet.Funktionen: Einloggen  |  Neu registrieren  |  Suchen

VB.NET - Ein- und Umsteiger
Aktualisieren aller Daten im DataTable eines DataSets 
Autor: spatzimatzi
Datum: 18.06.17 16:47

Hallo,
habe ein Problem und brauche eure Hilfe.

Derzeitige Situation:
Beim Start des Programmes wird eine Form mit einem DataGridView aufgerufen. Geladen werden die Daten mit Fill des DataAdapters und einer StoredProcedure
cmd.CommandText = "usp_SelectNotizenDC"
intAnz_Notizen = da.Fill(dsDatenPool, "Notizen")
Möchte der Anwender die Daten ändern, dann wird über die Auswahl einer Zeile im DataGridview eine neue Form aufgerufen und die Daten mit Hilfe des vorliegenden Schlüssels von der Datenbank gelesen
Auch dies geschieht mit eigenständigen Adaptern und StoredProcedure
Veränderungen an den Daten werden beim Verlassen der 2. Form direkt in der Datenbank hinterlegt und in der DataTable "Notizen" durchgeführt. Den Erfolg der Änderung sieht der Anwender direkt in seinem DataGridView der 1. Form.

Damit der 2. Anwender die Änderung erkennt, muss eine Aktualisierung seiner Daten stattfinden.
Dabei wird die Fill-Methode, die im Load-Ereigniss das DataGridView gefüllt hat, nochmals ausgeführt.
Die Anpassung wird vollzogen. Man kann in der Aktualisierung auch nur die Records lesen, die ab einem bestimmten Zeitpunkt Veränderungen erfahren haben. Es funktioniert auch zeitgesteuert. Z.B. alle 2 Minuten. Das läuft einwandfrei.
Sollte es ein besseres Verfahren geben, dann würde ich mich über Informationen freuen.

Nun zu meinem Problem:
Das Problem tritt beim Einfügen eines neuen Datensatzes auf.
Wird beim Einfügen die 2. Form verlassen, dann wird der neue Datensatz in die Datenbank geschrieben und die Schlüsselnummer wird zurückgegeben.
Danach wird auch die DataTable "Notizen" mit einem neuen Datensatz gefüllt. Dafür wird die Schlüsselnummer verwendet. Auch das geschieht noch einwandfrei.

Der Fehler tritt bei der Aktualisierung (wenn alle Änderungen eingespielt werden) auf.
Der Fehler lautet:
System.Data.ConstraintException: Einschränkungen konnten nicht aktiviert werden.
Mindestens eine Zeile enthält Werte die die Werte für die Einschränkungen non-null, unique or foreign-key verletzen.

Der eingefügte Datensatz erscheint im DataGridview 2 mal. Bei beiden Records wird ein roter Kreis mit einem Ausrufezeichen beim Schlüsselfeld eingeblendet. Deshalb vermute ich, dass der Fehler im Schlüsselfeld liegt.
Der Tooltipp des roten Kreises hat folgenden Inhalt:
Die Spalte 'NotizenIdent' hat die Einschränkung, dass sie eindeutig sein muss. Der Wert ... ist bereits vorhanden

Ich verstehe, dass der Schlüssel nur einmal vorhanden sein darf.
Da die veränderten Records aus der Datenbank direkt aktualisiert werden, hatte ich gedacht, dass geht auch mit den neuen Records.
Habe auch experimentiert mit
- da.FillSchema(dsDatenPool, SchemaType.Source, "Notizen")und
- da.MissingSchemaAction = MissingSchemaAction.AddWithKey
damit die Informationen des Schlüsselfeldes der Tabelle im DataSet bekannt sind.
Aber keine Änderung.

Jetzt die berühmte Frage: Was mache ich falsch? Habe ich ein Verständnisproblem?

Ich freue mich schon jetzt über zahlreiche Informationen und Hinweise

Danke
spatzimatzi
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Aktualisieren aller Daten im DataTable eines DataSets 
Autor: Manfred X
Datum: 18.06.17 18:21

Hallo!

Was bedeutet hier 2. Form bzw. 2. Anwender??

Bei Abfragen einer Multi-User-DB sind in der DB die
abgefragten Datensätze mit einem Zeitstempel zu versehen.
Für andere Nutzer dürfen diese gestempelten Sätze nicht
(für Änderungen oder prinzipiell) verfügbar sein.

Ansonsten gibt es z.B. die Möglichkeit der Abfrage-Benachrichtigung
(Stichwort: SQLDependency).
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Aktualisieren aller Daten im DataTable eines DataSets 
Autor: effeff
Datum: 18.06.17 18:27

Zitat:

Wird beim Einfügen die 2. Form verlassen, dann wird der neue Datensatz in die Datenbank geschrieben und die Schlüsselnummer wird zurückgegeben.


Wie schreibst Du den Datensatz genau in die Datenbank?

Zitat:

Danach wird auch die DataTable "Notizen" mit einem neuen Datensatz gefüllt. Dafür wird die Schlüsselnummer verwendet. Auch das geschieht noch einwandfrei.


Wie kommt der neue Datensatz in die DataTable?

Zitat:

Da die veränderten Records aus der Datenbank direkt aktualisiert werden, hatte ich gedacht, dass geht auch mit den neuen Records.


Wie werden die Daten aktualisiert?

EALA FREYA FRESENA

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Aktualisieren aller Daten im DataTable eines DataSets 
Autor: spatzimatzi
Datum: 18.06.17 19:29

Hallo Manfred X, hallo effeff,
vielen Dank für eure Hinweise.

@Manfred X
Die 2. Form ist die Einzeldarstellung der Notiz
In der 1. Form habe ich nur das DataGridView mit allen Notizen.
Diese Form wird ausschließlich für die Auswahl angezeigt

Unter dem 2. Anwender kann man jemanden verstehen, der in welcher Form auch immer Veränderungen an der Datenbank vornimmt. Z.B. über das Microsoft SQLServer Management Studio oder über ein Fremdprogramm

Die Records haben keinen Zeitstempel und sind jederzeit von jedermann aufrufbar.
Die Veränderungen an der DB-Tabelle (Nicht Insert) werden mit dem SQLAdapter durchgeführt

Eine Frage:
Was gibt mir SQLDependency zurück? Wie kann ich die Informationen einsetzen bzw. nutzen?

@effeff
Der neue Record wird direkt über eine StoredProcedure erzeugt

      con.ConnectionString = strConnectionString
      Dim cmdNew As New SqlCommand
      cmdNew.Connection = con
      cmdNew.CommandType = CommandType.StoredProcedure
      cmdNew.CommandText = "usp_IdentityNewNotizen"
 
      With cmdNew
        With .Parameters
          .Add("@AdressenIdent", SqlDbType.Int).Value = bsNotizenSng.Current( _
            "AdressenIdent")
          .Add("@ArtikelIdent", SqlDbType.Int).Value = bsNotizenSng.Current( _
          "ArtikelIdent")
          .Add("@LieferantenIdent", SqlDbType.Int).Value = bsNotizenSng.Current( _
          "LieferantenIdent")
          .Add("@Kurznotiz", SqlDbType.VarChar, 100).Value = _
          bsNotizenSng.Current("Kurznotiz")
          .Add("@Notiz", SqlDbType.Text).Value = bsNotizenSng.Current("Notiz")
 
          .Add("@identity", SqlDbType.Int).Direction = ParameterDirection.Output
 
        End With
      End With
 
      If con.State = ConnectionState.Closed Then con.Open()
 
      cmdNew.ExecuteNonQuery()
      bsNotizenSng.Current("NotizenIdent") = cmdNew.Parameters( _
        "@identity").Value
      intNotizenIdent = cmdNew.Parameters("@identity").Value
 
      ...
Die StoredProcedure sieht so aus:
ALTER PROCEDURE [dbo].[usp_IdentityNewNotizen]
	@AdressenIdent int,
	@ArtikelIdent int,
	@LieferantenIdent int,
	@Kurznotiz varchar(100),
	@Notiz varchar(MAX),
	@identity int OUTPUT	-- Rückgabewert
AS
BEGIN	
	SET NOCOUNT ON
 
	-- Anlegen eines neuen Records und Rückgabe,
	-- des SCOPE_IDENTITY()
	-- ----------------------------------------------------------------------------
	--BEGIN TRY	
		INSERT INTO tblNotizen(
			AdressenIdent,
			ArtikelIdent,
			LieferantenIdent,
			Kurznotiz,
			Notiz)
		VALUES (
			@AdressenIdent,
			@ArtikelIdent,
			@LieferantenIdent,
			@Kurznotiz,
			@Notiz)
 
		SET @identity = SCOPE_IDENTITY()
Das Schreiben in die Tabelle des DataSets geschieht mit folgendem Code

          Dim dv As DataView = New DataView(dsDatenPool.Tables("Notizen"))
          Dim NewRow As DataRowView = dv.AddNew()
          NewRow.BeginEdit()
          NewRow("NotizenIdent") = bsNotizenSng.Current("NotizenIdent")
          NewRow("ArtikelIdent") = 0
          NewRow("ArtikelNummer") = ""
          NewRow("AdressenIdent") = 0
          NewRow("AdressenNummer") = ""
          NewRow("LieferantenIdent") = 0
          NewRow("LieferantenNummer") = ""
          NewRow("Gruppe") = "Global"
          NewRow("Kurznotiz") = bsNotizenSng.Current("Kurznotiz")
          NewRow("DatenAnlageAm") = System.DateTime.Now.ToString("yyyy.MM.dd")
          NewRow.EndEdit()
Ansonsten werden die Daten über SQLAdapter angepasst.

Stehe jederzeit für Frage zur Verfügung

spatzimatzi
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Aktualisieren aller Daten im DataTable eines DataSets 
Autor: Manfred X
Datum: 19.06.17 11:28

Hallo!

[I]Unter dem 2. Anwender kann man jemanden verstehen,
der in welcher Form auch immer Veränderungen an der Datenbank vornimmt.
Z.B. über das Microsoft SQLServer Management Studio oder über ein Fremdprogramm

Die Records haben keinen Zeitstempel und sind jederzeit von jedermann aufrufbar.[/I]

Damit dürfte Dein Problem bereits benannt sein.
Wenn mehrere Nutzer parallel Datensätze ändern/anlegen können,
muß eine geeignete Koordination dieser Operationen erfolgen.
Entweder beim Select/Update von Daten werden Sperr-Einträge in den Tabellen
beachtet/gesetzt oder Sätze werden (zumindest) während der Transaktionen "gelockt".
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Aktualisieren aller Daten im DataTable eines DataSets 
Autor: spatzimatzi
Datum: 19.06.17 12:22

Hallo Manfred X,
mein Problem tritt doch schon auf, wenn nur ich den neuen Satz in die DataTable einfüge und manuell danach die Aktualisierung der kompletten DataTable ausführe. Damit verhalte ich mich so, als würde eine Multiuser-Anwendung vorliegen.
Normalerweise sollte jeder Satz ein oder auch mehrere Schlüsselfelder haben um die Eindeutigkeit zu gewährleisten. Bei einem anschließenden Select und Fill auf die DataTable werden dann die schon vorliegenden Records upgedated und neue Records eingefügt. Nun ist es so, dass die Records fehlerfrei upgedated werden, aber bei einem Insert kein Update erfolgt sondern eben ein zusätzlicher Insert. Da aber der Satz schon vorliegt, kommt es zum Konflikt. Aber eben warum? Wird der Schlüssel nicht erkannt, um die Eindeutigkeit zu sehen.
Hab doch auch
- da.FillSchema(dsDatenPool, SchemaType.Source, "Notizen")und
- da.MissingSchemaAction = MissingSchemaAction.AddWithKey
getestet. Keine Änderung.


Thema: Multiuser
Vielleicht habe ich es auch falsch verstanden. Aber nach meinem Verständnis ist ein Zeitstempel, auch im MultiUser-Betrieb, nicht unbedingt notwendig.
Änderungen an den Tabellen in der Datenbank laufen in meinem Fall immer über den SQLDataAdapter.
Beim UPDATE erkennt der SQLDataAdapter entweder an Hand des Zeitstempels oder im Vergleich aller Felder der Tabelle, dass ein anderer User die Daten in der Datenbank schon angepasst hat.
Entsprechend kann dann bei der Parallelitätsverletzung gehandelt werden.

Aber häufig gibt es einen Unterschied zwischen "Wissen" und "Glauben"
Sollte ich mich täuschen, dann würde ich mich freuen über zusätzliche Informationen.

Viele Grüße
spatzimatzi
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Aktualisieren aller Daten im DataTable eines DataSets 
Autor: effeff
Datum: 19.06.17 12:41

So...

Du schreibst also die Daten einmal direkt in die Datenbank und dann noch zusätzlich in die DataTable; Kein Wunder, dass die Daten dann mehrfach darin enthalten sind, oder? Natürlich knallt das, wenn Du dann ein Update versuchst.

Wie wäre es denn mit: Daten direkt in Datenbank, Daten dann updaten, damit die neuen Daten auch in der DataTable enthalten sind?

EALA FREYA FRESENA

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Aktualisieren aller Daten im DataTable eines DataSets 
Autor: spatzimatzi
Datum: 19.06.17 13:03

Hallo effeff,
grundsätzlich hast du Recht.
Ich könnte die Daten in die DB schreiben und dann die Komplettaktualisierung machen.
Das würde sicherlich auch klappen. Auch mit dem Insert.
Hätte auch den Vorteil, dass Änderungen anderer User sofort mit upgedated würden
Werde ich testen.

Aber ich wollte meinem Vorgehen treu bleiben.

Wenn ich in der 2. Form Änderungen vornehme, dann schreibe ich diese Änderungen auch in die DataTable und in die Datenbank. Wird dann eine Komplettaktualisierung durchgeführt, dann gibt es auch keine Probleme. Und da dachte ich mir, wird es wohl beim Insert auch klappen. Gleiche Abläufe, Schlüsselinhalt ist korrekt
Mir fällt gerade ein:
Führt evtl. die DataRow noch irgendwelche Kenner nach dem Insert in die DataTable.

Der Nachteil beim Insert immer eine Komplettaktualisierung durchzuführen ist auch der, dass der Datenumfang immer größer wird. Hier müsste ich dann auf Teilaktualisierung umstellen, um das Netz zu entlasten.

Viele Grüße
spatzimatzi
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Aktualisieren aller Daten im DataTable eines DataSets 
Autor: spatzimatzi
Datum: 19.06.17 14:05

Hallo Manfred X, hallo effeff,
habe das Problem gelöst.

Nach dem Insert in die DataTable führe ich ein
dsDatenPool.Tables("Notizen").AcceptChanges()
durch.
Jetzt reagiert das System genau so, wie ich es mir vorstelle!

Erstaunlich ist es, dass man bei Änderungen kein AcceptChanges benötigt

Vielen Dank für eure Anregungen
spatzimatzi
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Aktualisieren aller Daten im DataTable eines DataSets 
Autor: Manfred X
Datum: 19.06.17 15:48

Hallo!

Das Anlegen neuer Datensätze mit automatisch erzeugten (eindeutigen)
Schlüsseln, sollte meiner Ansicht nach durch eine in der DB eingebettete
Routine erfolgen (Erstellung und Rückgabe eines neuen Datensatzes mit
den Primär-Schlüsselwerten).
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Aktualisieren aller Daten im DataTable eines DataSets 
Autor: Manfred X
Datum: 19.06.17 15:59

Wenn Du eine Update der Datensätze (erfolgreich) in der DB durchführst,
werden alle Änderungen persistent (=AcceptChanges).

Wenn diese Methode direkt im Code aufgerufen wird, werden zuvor durchgeführte
Daten-Änderungen im Dataset bei einem späteren Update nicht mehr erkannt und
können deshalb auch nicht in die Datenbank übertragen werden.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Aktualisieren aller Daten im DataTable eines DataSets 
Autor: Manfred X
Datum: 19.06.17 16:08

Wieso bindest Du das zweite Grid nicht an die bereits durchgeführte
Abfrage (z.B. gefiltertes Dataview) ????
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Aktualisieren aller Daten im DataTable eines DataSets 
Autor: spatzimatzi
Datum: 19.06.17 16:15

Hallo Manfred X,
Thema: Datenbank
die Datensätze werden durch eine StoredProcedure in der Datenbank angelegt.
Der Primär-Schlüssel wird auch von der Datenbank erzeugt
Mit SCOPE_IDENTITY() lasse ich mir diesen Primär-Schlüssel zurückgeben

Thema: Update der DataTable
Das DataGridView und die gebundene DataTable werden ausschließlich zur Datenausgabe genutzt.
Der Anwender kann sich über die Records einen Überblick verschaffen und einen Datensatz für die Anzeige auswählen. In dieser Anzeige kann er dann entscheiden, ob er den Datensatz löschen oder editieren möchte.
Da das DataGridView und die DataTable ausschließlich der Anzeige dienen, kann ein AcceptChanges durchgeführt werden.
Aus dieser DataTable werden niemals Änderungen auf der Datenbank durchgeführt

Viele Grüße
spatzimatzi
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Aktualisieren aller Daten im DataTable eines DataSets 
Autor: spatzimatzi
Datum: 19.06.17 16:34

Hallo Manfred X,
meinst du das Grid in dem Dataset oder das DataGridView auf dem Desktop

programmtechnisch laufen alle Aufrufe zur Datenbank nach dem gleichen Muster ab.

Im DataGridView werden alle Records der Datengruppe gezeigt.
Hier kann ein bestimmter Datensatz selektiert werden (z.B. eine bestimmte Notiz)
Diese Notiz wird dann in einer neuen Form bearbeitet oder editiert.
Und diese eine Notiz wird dann auch die Datenbank verändert. Und es wird die Übersicht angepasst.

Die Fülle der Daten bei Notizen pro Record in der Übersicht und in der Einzelansicht ist fast identisch. Hier hätte man das Verfahren ändern können.

Verarbeitet man aber Artikeldaten, dann ist das Verhältnis zwischen Übersicht und Einzelansicht schnell 1/10 oder 1/40, mit einer deutlich höheren Netzbelastung.
Deshalb hat man sich für eine Trennung entschieden.

Hoffe, ich habe deine Frage richtig verstanden

Viele Grüße
spatzimatzi
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Aktualisieren aller Daten im DataTable eines DataSets 
Autor: Manfred X
Datum: 19.06.17 17:10

[I]Verarbeitet man aber Artikeldaten, dann ist das Verhältnis
zwischen Übersicht und Einzelansicht schnell 1/10 oder 1/40,
mit einer deutlich höheren Netzbelastung.[/I]

Das verstehe ich nicht. Beim Update werden nur die Sätze aktualisiert,
die tatsächlich im Dialog geändert worden sind.
Schau Dir mal die Rowstate-Einträge der Datensätze der Gesamtansicht an.
Diese Sätze sollten als "unchanged" markiert sein - auch ohne AcceptChanges!

Ich vermute, Du fügst neu gelesene Datensätze in die bereits geladene Table ein
oder änderst sie per Code auf aktuell ermittelte DB-Werte.
Deren Rowstate mußt Du explizit auf Unchanged setzen, sonst werden sie
beim Update eingeschlossen.
Dann kannst Du auf die Doppel-Abfrage verzichten.

Nur die im Benutzer-Dialog gelöschten/hinzugefügten oder geänderten Datensätze
dürfen entsprechende RowState-Werte aufweisen.

Beitrag wurde zuletzt am 19.06.17 um 17:27:44 editiert.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Aktualisieren aller Daten im DataTable eines DataSets 
Autor: spatzimatzi
Datum: 19.06.17 17:32

Hallo Manfred X,
ich habe mich falsch ausgedrückt.

Das Verhältnis in der Anzahl der Spalten (Felder) liegt bei 1/10 bis 1/40

Ein UPDATE über den SQLDataAdapter findet in der Regel mit nur einem Record statt.

Viele Grüße
Spatzimatzi
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Sie sind nicht angemeldet!
Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.

Einloggen  |  Neu registrieren

Funktionen:  Zum Thema  |  GesamtübersichtSuchen 

nach obenzurück
 
   

Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel