[vb2005] Meerdere gebruikers voegen records toe

Pagina: 1
Acties:

  • Sjakskus
  • Registratie: Maart 2002
  • Laatst online: 28-11 15:34
Ik heb een form, waar gebruikers gegevens in een tabel (SQL Express) kunnen vullen
De primary key (het veld ID) van die tabel is een int die autoincrement.
dit werkt met 1 user tegelijk perfect, maar als 2 of meer users tegelijk werken, krijgen zij beide bv nr 12 in het veld ID.

Dit is natuurlijk niet wenselijk en gaat met het opslaan ook fout omdat de ID 12 2x voorkomt.

Dit heb ik nu als volgt opgelost:
als men op de knop "nieuw record" drukt, dan:
  • Wordt eerst de dataset opnieuw geladen
  • daarna wordt er een record toegevoegd
  • Dit record wordt meteen opgeslagen
Is dit de enige manier om dit te doen?
Het lijkt me namelijk een beetje omslachtig om iedere keer de dataset opnieuw te vullen, als er een nieuw record wordt toegevoegd.

Beschikbaar voor ontwikkeling van (webbased) applicaties en dataconversies


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Zoek eens op Concurrency Control ;) (evt. verfijnen met VB.net ofzo)

Zelf hier @GoT is er voldoende te vinden lijkt me.

[ Voor 152% gewijzigd door RobIII op 13-03-2007 18:29 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • Sjakskus
  • Registratie: Maart 2002
  • Laatst online: 28-11 15:34
ok tnx.... d:)b
nog nooit van gehoord en heb toch ook best al wat gegoogled.
Dit is mijn eerste multi user db dus tast nog een beetje in het duister

Beschikbaar voor ontwikkeling van (webbased) applicaties en dataconversies


  • Sjakskus
  • Registratie: Maart 2002
  • Laatst online: 28-11 15:34
Ik heb net ff zitten googlen, maar kom alleen maar bij voorbeelden, waarbij men tegelijkertijd een bestaand record opent en dat wijzigt.

Ook in de help kan ik wel vinden hoe optimistic en pessimistic concurrency control werkt, maar zijn dat functies die je aan kan roepen, zodat dit automatisch wordt geregeld of is het zo, dat je op basis van deze methodes zelf een script moet programmeren?

Kan iemand aub een voorbeeld geven van hoe je tijdens het toevoegen van een nieuw record hier rekening mee houd?

[ Voor 12% gewijzigd door Sjakskus op 13-03-2007 21:15 ]

Beschikbaar voor ontwikkeling van (webbased) applicaties en dataconversies


  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Dit zijn dingen welke je echt bewust zelf moet willen afhandelen. Je kan zelf nog het beste bepalen waar de critical regions zitten. Je hebt dus blokken code welke je dus niet parallel uitgevoerd wil zien, omdat er dan een race conditie kan optreden.

Ook jouw voorgestelde aanpak in de topicstart is niet goed genoeg: je verkort dan wel de tijdspanne waarin het fout kan gaan, maar client B kan nog steeds vlak voordat client A stap 2 uitvoert ook een record aanmaken.

{signature}


  • whoami
  • Registratie: December 2000
  • Laatst online: 00:54
Je doet dus het volgende: je wil een nieuw record maken; om dit te doen haal je alle bestaande records uit de DB, in een dataset, je maakt een nieuw record in die dataset, en dan ga je die dataset (althans de wijzigingen, dat ene nieuwe record), gaan wegschrijven ?
Beetje omslachtig en onnodig veel DB en netwerk-verkeer, denk je niet ?

Waarom ga je niet gewoon gebruik maken van een SqlCommand dat gewoon een INSERT query voorstelt, en dan dit INSERT command gaan uitvoeren ? Dan zal je zowiezo geen probleem hebben met dubbele identities.
Nu heb je dat probleem (met die dubbele identities dus), omdat ik vermoed dat je dataset je lokaal een nieuwe identity toewijst. Gebruiker B heeft dus geen weet wat gebruiker A doet.
Zowiezo is het omslachtig om een hele dataset uit de DB op te halen, om enkel een nieuw record in de DB te stoppen; ik bedoel: je haalt bv 10.000 records op, stuurt deze allemaal naar de client, om er vervolgens ..... niets mee te doen.

Als je toch via deze manier wil verder werken (dus, de dataset ophalen, en dan zo met je data-adapter de wijzigingen gaan wegschrijven), dan zet je best de AutoIncrementSeed van je identity field in je Dataset op -1, en je AutoIncrementStep van dat veld in je dataset ook op -1.
Als je dus een nieuw record in je DataSet gaat invoeren, dan gaat dat record als id -1 krijgen, als je er nog een aan toevoegt, krijgt het -2 als id, etc...
Normaal gezien zou de DB -als het veld ook daar een identity is- zelf een ID moeten toewijzen aan dat veld (en dus niet -1, -2, oid gebruiken). In de RowUpdated event kan je dan het ID gaan ophalen dat de DB aan je record heeft toegewezen (select @@identity, select scope_identity(), ... ).

Echter, als het enkel gaat om een record bij te maken, en je die andere niet nodig hebt, zou ik het niet via de DataSet manier doen; gewoon zo:
code:
1
2
3
4
5
6
SqlCommand cmd = new SqlCommand ();
....
cmd.CommandText = "INSERT INTO tabel ( veld1, veld2) VALUES (@v1, v2)";
cmd.Parameters.Add ("@v1", SqlDbType.Varchar).Value="bliep";
cmd.Parameters.Add ("@v2", SqldBType.Varchar).Value="melp";
cmd.ExecuteNonQuery();

[ Voor 10% gewijzigd door whoami op 13-03-2007 22:56 ]

https://fgheysels.github.io/


  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Simpele ( lelijke ) oplossing die ik nog wel eens gebruik is gewoon bij opslaan eerst een insert uitvoeren met de gegevens. Hieruit krijg je een id, dan het hoogste bonnr uit de tabel opvragen. Dan het hoogste bonnr +1 aan het nieuwe id geven, en als dit failed dan opnieuw het hoogste bonnr uit de tabel opvragen en bonnr+1 aan het nieuwe id geven. Net zolang tot het lukt.

Btw dit is puur ooit eens geschreven voor een klant die erg bang was voor race-conditions. Maar in de praktijk is het nooit voorgekomen ( als de update failed dan wordt er ook nog iets in een error-log geschreven ).

P.s. hoogste bonnr is ook niet een max() query, maar gewoon een apart tabelletje/veldje met daarin het huidige hoogste bonnr, voordat er mensen beginnen te zeuren dat we onnodig zware querys op de dbase afvuren...

  • Sjakskus
  • Registratie: Maart 2002
  • Laatst online: 28-11 15:34
whoami bedankt voor je uitgebreide antwoord.

Je methode voldoet in principe wel, maar als ik die insert uitvoer, dan weet ik niet wat de ID van dat record is. en dat is iets wat ik op dat moment nog nodig heb,.

Kan ik die op de een of andere manier dan nog achterhalen?

Beschikbaar voor ontwikkeling van (webbased) applicaties en dataconversies


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Sjakskus schreef op woensdag 14 maart 2007 @ 00:45:
whoami bedankt voor je uitgebreide antwoord.

Je methode voldoet in principe wel, maar als ik die insert uitvoer, dan weet ik niet wat de ID van dat record is. en dat is iets wat ik op dat moment nog nodig heb,.

Kan ik die op de een of andere manier dan nog achterhalen?
Dat geeft 'ie toch al aan?
whoami schreef op dinsdag 13 maart 2007 @ 22:54:
In de RowUpdated event kan je dan het ID gaan ophalen dat de DB aan je record heeft toegewezen (select @@identity, select scope_identity(), ... ).
Lelijk én ranzig :X
Je zit gewoon functionaliteit die je DB gewoon zelf bevat nog eens dunnetjes over te doen met hulptabellen en gaat dan doodleuk "zitten proberen tot het een keer lukt". Dit is so not the way to go ;)

[ Voor 20% gewijzigd door RobIII op 14-03-2007 01:04 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • Sjakskus
  • Registratie: Maart 2002
  • Laatst online: 28-11 15:34
ROBIII

ik bedoel bij manier 1

Ik voer onderstaande code uit.
Visual Basic .NET:
1
2
3
        cmd.CommandText = "INSERT into transacties (trans_tijd) VALUES (@V1)"
        cmd.Parameters.Add("@v1", SqlDbType.DateTime).Value = Now
        cmd.ExecuteNonQuery()


Hiermee vul ik alleen het veld trans_tijd. Het veld trand_id is een identify/autoincrement veld en word dus automatisch gevuld, maar kan ik de inhoud van dat veld ook achterhalen?

Beschikbaar voor ontwikkeling van (webbased) applicaties en dataconversies


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Sjakskus schreef op woensdag 14 maart 2007 @ 01:25:
Hiermee vul ik alleen het veld trans_tijd. Het veld trand_id is een identifty/autoincrement veld en word dus automatisch gevuld, maar kan ik de inhoud van dat veld ook achterhalen?
Als je nou eens de moeite neemt om even te googlen:
After an INSERT, SELECT INTO, or bulk copy statement is completed, @@IDENTITY contains the last identity value that is generated by the statement.
Dat is precies wat jij wil.

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 10:24

gorgi_19

Kruimeltjes zijn weer op :9

Waarbij je niet @@Identity maar Scope_Identity moet gebruiken, anders kan je alsnog onvoorspelbare resultaten krijgen :P
@@IDENTITY and SCOPE_IDENTITY return the last identity value generated in any table in the current session. However, SCOPE_IDENTITY returns the value only within the current scope; @@IDENTITY is not limited to a specific scope.

[ Voor 50% gewijzigd door gorgi_19 op 14-03-2007 08:44 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • whoami
  • Registratie: December 2000
  • Laatst online: 00:54
gorgi_19 schreef op woensdag 14 maart 2007 @ 08:43:
Waarbij je niet @@Identity maar Scope_Identity moet gebruiken, anders kan je alsnog onvoorspelbare resultaten krijgen :P

[...]
Idd, ik gebruik ook liefst scope_identity, maar als je geen triggers enzo gebruikt, is @@identity ook goed. :P
Sjakskus schreef op woensdag 14 maart 2007 @ 01:25:
ROBIII

ik bedoel bij manier 1

Ik voer onderstaande code uit.
Visual Basic .NET:
1
2
3
        cmd.CommandText = "INSERT into transacties (trans_tijd) VALUES (@V1)"
        cmd.Parameters.Add("@v1", SqlDbType.DateTime).Value = Now
        cmd.ExecuteNonQuery()


Hiermee vul ik alleen het veld trans_tijd. Het veld trand_id is een identify/autoincrement veld en word dus automatisch gevuld, maar kan ik de inhoud van dat veld ook achterhalen?
Ook gewoon met scope_identity of @@identity; waarom zou dit anders zijn (het achterhalen v/h id) dan op die andere manier ?

[ Voor 49% gewijzigd door whoami op 14-03-2007 08:51 ]

https://fgheysels.github.io/

Pagina: 1