Toon posts:

[C#] Laatste insert id uit MSSQL DB halen

Pagina: 1
Acties:

Verwijderd

Topicstarter
Op internet heb ik gevonden dat dit kan met "SELECT @@Identity", maar het is mij nog onduidelijk hoe dit precies werkt, ik heb het in ieder geval nergens kunnen vinden.

Ongetwijfeld zal je dit als query op de database uit moeten voeren, maar dan vraag ik mij weer af hoe ik het resultaat ervan in een variabele krijg 8)7

Kan iemand mij verder helpen?

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 16:50

gorgi_19

Kruimeltjes zijn weer op :9

1. Gewoon behandelen als 'recordset' en als zodanig uitlezen.
2. Door middel van ExecuteScalar de SP uitvoeren en deze returnwaarde uitlezen.
3. Ombouwen naar een output parameter en als zodanig uitlezen.

Verder ben ik heel benieuwd hoe je hebt gezocht.

Google met de zoekwoorden C# @@Identity gaf gelijk de eerste link een van de drie oplossingen.

[ Voor 41% gewijzigd door gorgi_19 op 22-09-2003 12:43 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
@@identity is gewoon een waarde in MSSQL server die per connection de laatste ingevoegde identity bijhoud.
Het is in principe dus hetzelfde als

Select 'blaat'

alleen wordt @@identity vervangen door het laatst ingevoegde identity dus het is gewoon ene normale query die je netzoals elke andere query kan benaderen.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • P_de_B
  • Registratie: Juli 2003
  • Niet online
En om zeker te weten dat je de goede Identity krijgt, kun je beter SCOPE_IDENTITY gebruiken. Met @@Identity loop je het risico dat je een ID van een andere tabel krijgt.

Oops! Google Chrome could not find www.rijks%20museum.nl


  • whoami
  • Registratie: December 2000
  • Laatst online: 23:34
Test het gewoon eens in Query Analyzer, en kijk wat je terugkrijgt.

Verder heeft P_de_B helemaal gelijk ivm die scope_identity() functie.

Om het helemaal veilig te doen, dan maak je eigenlijk best een stored procedure waarin je de INSERT doet, en die het id van dat record mbhv scope_identity als een output-parameter returned.

https://fgheysels.github.io/


  • Skaah
  • Registratie: Juni 2001
  • Niet online
is
SQL:
1
select Id from tabel order by Id DESC LIMIT 1

Is MySQL maar zou toch ook (bijna) moeten werken met MSSQL?

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 16:50

gorgi_19

Kruimeltjes zijn weer op :9

Skaah schreef op 22 September 2003 @ 13:23:
is
SQL:
1
select Id from tabel order by Id DESC LIMIT 1

Is MySQL maar zou toch ook (bijna) moeten werken met MSSQL?
Wie garandeert jou dat dit deze ID bij jou hoort? Misschien is er wel een record tussen geslopen van iemand anders.

Daarnaast wil een identity niet een opeenvolgend iets garanderen.

[ Voor 11% gewijzigd door gorgi_19 op 22-09-2003 13:25 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • whoami
  • Registratie: December 2000
  • Laatst online: 23:34
Skaah schreef op 22 September 2003 @ 13:23:
is
SQL:
1
select Id from tabel order by Id DESC LIMIT 1

Is MySQL maar zou toch ook (bijna) moeten werken met MSSQL?
Zoals gorgi al zegt, is die methode totaal onveilig. Je wordt niet gegarandeerd van het juiste resultaat.
Daarnaast is ze ook nog eens veel trager, aangezien de volledige table eerst gesorteerd moet worden.

https://fgheysels.github.io/


Verwijderd

Topicstarter
whoami schreef op 22 September 2003 @ 12:59:
Test het gewoon eens in Query Analyzer, en kijk wat je terugkrijgt.

Verder heeft P_de_B helemaal gelijk ivm die scope_identity() functie.

Om het helemaal veilig te doen, dan maak je eigenlijk best een stored procedure waarin je de INSERT doet, en die het id van dat record mbhv scope_identity als een output-parameter returned.
Ok, ik heb de query uitgevoerd in de query analyzer en ik krijg netjes de laatste id terug.
In mijn progsel werkt het ook, maar krijg ik nu een object terug.
De code is voorlopig als volgt:
code:
1
2
3
4
5
6
object last_id;
SqlCommand query = new SqlCommand("select scope_identity() as id", myConnection);
query.Connection.Open();
last_id = query.ExecuteScalar();
int id = ToInt32(last_id);
query.Connection.Close();


Nu wil ik natuurlijk heel graag van dat object een int maken. MSDN zegt dat je dat kan doen met
code:
1
2
3
public static int ToInt32(
    object value
);

en dat zal best, maar ik heb geen idee hoe ik die moet implementeren aangezien er geen voorbeelden van zijn.

wie helpt me nog 1 keer uit de brand? :)

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 16:50

gorgi_19

Kruimeltjes zijn weer op :9

Convert.ToInt32()

Int32.Parse()

Ow ja, ik ben VB.Net gewend, dus case mag je zelf uitvogelen.

[ Voor 49% gewijzigd door gorgi_19 op 22-09-2003 13:44 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • whoami
  • Registratie: December 2000
  • Laatst online: 23:34
Verwijderd schreef op 22 September 2003 @ 13:42:
[...]


Nu wil ik natuurlijk heel graag van dat object een int maken. MSDN zegt dat je dat kan doen met
code:
1
2
3
public static int ToInt32(
    object value
);

en dat zal best, maar ik heb geen idee hoe ik die moet implementeren aangezien er geen voorbeelden van zijn.

wie helpt me nog 1 keer uit de brand? :)
Die ToInt32 is een static method van de Convert class.

Gewoon door Convert.ToInt32 aan te roepen dus met het gewenste object als parameter, en die returned dan het resultaat van de conversie....
Daar heb je toch geen voorbeelden voor nodig?

https://fgheysels.github.io/


  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 16:50

gorgi_19

Kruimeltjes zijn weer op :9

Het enige nadeel van een ExecuteScalar vind ik dat je in de problemen kan komen als je geen returnwaarde stiekem krijgt. :)

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • whoami
  • Registratie: December 2000
  • Laatst online: 23:34
gorgi_19 schreef op 22 september 2003 @ 13:48:
Het enige nadeel van een ExecuteScalar vind ik dat je in de problemen kan komen als je geen returnwaarde stiekem krijgt. :)
Idd. Je kan dus wel eerst checken of het object dat je gereturned krijgt niet gelijk is aan DBNull.Value ofzo.
Maareh, een select @@identity zal wel altijd een waarde returnen....

Daarnaast blijf ik bij mijn eerdere optie ivm die Stored procedures enzo. :P

https://fgheysels.github.io/


  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 16:50

gorgi_19

Kruimeltjes zijn weer op :9

whoami schreef op 22 September 2003 @ 13:51:
[...]


Idd. Je kan dus wel eerst checken of het object dat je gereturned krijgt niet gelijk is aan DBNull.Value ofzo.
Maareh, een select @@identity zal wel altijd een waarde returnen....
Klopt, alleen een kleine kanttekening bij die executescalar dat je hem niet altijd kan gebruiken.. Ik had namelijk hem geprobeerd om te gebruiken bij het inloggen; voor het achterhalen bij een UserID. Dat casten naar een int ging alleen niet zo goed als de inlognaam / wachtwoord fout was.. :X Outputparameter was toen ietsie beter; qua performance maakt dat ook niet zo veel niet (lees: niets).

Maar meer als sidenote dus.. :P

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Verwijderd

Topicstarter
gorgi_19 schreef op 22 September 2003 @ 13:48:
Het enige nadeel van een ExecuteScalar vind ik dat je in de problemen kan komen als je geen returnwaarde stiekem krijgt. :)
Inderdaad, maar als ik ipv ExecuteScalar ExecuteReader doe, dan gaat het weer fout bij het converteren naar een int (System.InvalidCastException: Specified cast is not valid.), terwijl die functies toch allebei objecten teruggeven.

Valt toch tegen dat C# :(

[ Voor 4% gewijzigd door Verwijderd op 22-09-2003 14:11 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 23:34
Verwijderd schreef op 22 september 2003 @ 14:09:
[...]


Inderdaad, maar als ik ipv ExecuteScalar ExecuteReader doe, dan gaat het weer fout bij het converteren naar een int (System.InvalidCastException: Specified cast is not valid.), terwijl die functies toch allebei objecten teruggeven.
Ik stel voor dat jij toch eerst en vooral dringend de help bekijkt, en meer bepaald de uitleg over ExecuteScalar en ExecuteReader.

ExecuteReader returned een datareader (die in feite ook wel een object is, aangezien alles inherited van object). Hoe je executeReader gebruikt, moet je toch eens in de help bekijken.

https://fgheysels.github.io/


  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 16:50

gorgi_19

Kruimeltjes zijn weer op :9

Verwijderd schreef op 22 September 2003 @ 14:09:
[...]


Inderdaad, maar als ik ipv ExecuteScalar ExecuteReader doe, dan gaat het weer fout bij het converteren naar een int (System.InvalidCastException: Specified cast is not valid.), terwijl die functies toch allebei objecten teruggeven.

Valt toch tegen dat C# :(
Dan doe je iets anders geks..
Visual Basic .NET:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
       Public Function GetGameID(ByVal userid As Integer) As Integer Implements IDataProvider.GetGameID
            ' Create Instance of Connection and Command Object
            Dim myConnection As SqlConnection = GetSqlConnection()
            Dim myCommand As New SqlCommand("Procedurenaam", myConnection)

            ' Mark the Command as a SPROC
            myCommand.CommandType = CommandType.StoredProcedure

            myCommand.Parameters.Add("@UserID", SqlDbType.Int, 4).Value = userid

            ' Execute the command
            myConnection.Open()
            Dim retVal As Integer = Int32.Parse(myCommand.ExecuteScalar())
            myConnection.Close()

            Return retVal

        End Function 'ValidUser

werkt bij mij iig goed.

[ Voor 33% gewijzigd door gorgi_19 op 22-09-2003 14:13 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Verwijderd

Topicstarter
Ik begrijp er weinig van nu,, als ik de Query doe met ExecuteScalar blijft het resultaat vervolgens _altijd_ leeg, terwijl als ik een query uitvoer in de SQL analyzer en dan "select scope_identity() as id" daarna doe, krijg ik wel een resultaat (het laatste id)

de code ziet er nu als volgt uit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SqlConnection myConnection = new SqlConnection("server=(local);database=patat;Trusted_Connection=true");
SqlCommand myCommand = new SqlCommand("INSERT INTO Musea ( <knip> ) VALUES ( <knip> )",  myConnection);

myCommand.Connection.Open();
myCommand.ExecuteNonQuery();
myCommand.Connection.Close();

int id = 0;
object new_id;
SqlCommand id_cmd = new SqlCommand("SELECT SCOPE_IDENTITY() AS id", myConnection);
id_cmd.Connection.Open();
new_id = id_cmd.ExecuteScalar();
id_cmd.Connection.Close();

if (new_id == DBNull.Value) {
     id = Convert.ToInt32(new_id);
}

Iemand die zie wat ik hier fout doe?

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:34
Scope_identity is beperkt tot de connectie waarin ze uitgevoerd wordt.

Jij gaat je connectie openen, de insert doen, je connectie sluiten, en een select scope_identity doen.
Logisch dat je daar niets terugkrijgt, aangezien die sessie niets geinserted heeft. (Je hebt nl. je connectie gesloten en heropend).

Ik vraag me trouwens af waarom je je connectie sluit na die insert, om ze dan opnieuw te gaan openen. Dat kost alleen maar tijd en resources. (Ok, als je met connection pooling werkt, zal het nog meevallen, maar toch is het onnodig).
Je hoeft je connectie pas te sluiten als je een lange / onbepaalde tijd geen DB accesss meer hoeft te doen.

https://fgheysels.github.io/


Verwijderd

Topicstarter
Owk, het kostte wat bloed, zweet en tranen, maar het is dan toch gelukt...

thx :)
Pagina: 1