views:

275

answers:

4

I'm using ADO.NET to try to get the value I'm about to insert before I insert it in SQL Server 2005. SCOPE_IDENTITY() works fine after, but I'm also inside a transaction if that makes a difference. I literally need to select the next ID, and only the ID and have it available to C# before the insert.

A: 

The SCOPE_IDENTITY will only work once you've inserted the row in to the table. If you need to know the value before you insert you will need to use IDENT_CURRENT('table_name'). See http://msdn.microsoft.com/en-us/library/ms175098.aspx for more information.

Chuck Haines
Thanks, but so far I've tried Ident_Current('mytable'), SELECT @newId = SCOPE_IDENTITY() FROM mytable, SELECT @newId = Ident_Current('CustomizedProducts) and directly selecting the ID without assigning it to an out parameter. I get a NULL every time.
Echilon
ident_current is dangerous to use for this, the actual transaction may not end up with the next available identity as there may be other transactions that happen or even rollbacks. Very bad idea.
HLGEM
Agreed that ident_current is dangerous but that's the best way even though it's not reliable or safe. There really is not way to get the value before an insert unless you don't use an identity and instead use a manual method.
Chuck Haines
Thanks Chuck. Not what I wanted, but I'll need to think of a way around it.
Echilon
unsafe: you absolutely need to serialize before you can safely use IDENT_CURRENT
AlexKuznetsov
A: 

try using IDENT_CURRENT. As MSDN says, "it returns the last identity value generated for a specific table in any session and any scope"

odiseh
use with care, though! Even though you might know the last generated value, there is **NO GUARANTEE** you can guess the next one that will be used from this!
marc_s
+2  A: 

Whatever solution you choose, make sure to test it under high concurrency. most likely it will break - two or more different connections will get the same ID before they insert. Before doing anything, I would use sp_getapplock to serialize access, so that there is no concurrency.

AlexKuznetsov
+1  A: 

As an alternative solution you could change your primary key type to a GUID type, this would then allow you to insert with a known key.

Guid pk = Guid.NewGuid();

I dont recall the method for SQL server if the class is directly supported or if you need to convert it to a byte[]. For oracle we convert to a char(32).

This way you dont need to worry about concurrency.

Thomas James
The Guid type is supported in in SQL server; it is called `uniqueidentifier`.
Kirk Broadhurst