web-dev-qa-db-fra.com

Retourner ID sur INSERT?

J'ai une requête INSERT et je veux que la base de données retourne l'ID de la ligne que je viens d'insérer.

sqlString = "INSERT INTO MagicBoxes (OwnerID, Key, Name, Permissions, Active, LastUpdated) VALUES (@OwnerID, @BoxKey, @BoxName, 0, 1, @Date) SET @ID = SCOPE_IDENTITY();";
cmd = new SqlCommand(sqlString, con);
cmd.Parameters.AddWithValue("@OwnerID", OwnerID);
cmd.Parameters.AddWithValue("@BoxKey", BoxKey);
cmd.Parameters.AddWithValue("@BoxName", BoxName);
cmd.Parameters.AddWithValue("@Username", Username);
cmd.Parameters.AddWithValue("@Date", DateTime.Now);
cmd.ExecuteNonQuery();

J'ai actuellement ceci, je ne suis pas sûr de ce que je dois faire ensuite ...

23
Danpe

Il vous suffit d’ajouter @ID à la collection params puis de le récupérer comme ceci, 

cmd.Parameters.Add("@ID", SqlDbType.Int, 4).Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
//Now just read the value of: cmd.Parameters["@ID"].value

Ou, si vous préférez cette syntaxe:

SqlParameter param = new SqlParameter("@ID", SqlDbType.Int, 4);
param.Direction = ParameterDirection.Output;
cmd.Parameters.Add(param);
33
AdaTheDev

Vous avez deux options. vous pouvez déclarer un paramètre Output appelé @ID; ou - vous pouvez changer la fin en SELECT SCOPE_IDENTITY() et simplement utiliser:

int id = (int)cmd.ExecuteScalar();

Je préfère l’approche paramétrique formelle, mais ExecuteScalar fonctionne bien.

21
Marc Gravell

Depuis SQL Server 2008, une clause OUTPUT a été ajoutée à la syntaxe de TSQL. Cela vous permet d'ajouter les données affectées par la requête DML au flux de données tabulaire. 

Bien que l'interrogation de SCOPE_IDENTITY () après une requête renvoie les informations correctes, elle oblige SQL Server à exécuter 2 requêtes lorsque la clause de sortie le limite à une requête. 

Sachant cela, la requête en cours d'exécution peut être modifiée comme suit (en supposant que [Id] est le nom de l'identité):

INSERT INTO MagicBoxes (OwnerID, [Key], Name, [Permissions], Active, LastUpdated) 
OUTPUT INSERTED.Id
VALUES (@OwnerID, @BoxKey, @BoxName, 0, 1, @Date)

Un autre problème est de ne pas disposer de la variable SqlCommand. La plupart des objets Sql... dans ADO.net implémentent IDisposable et doivent être éliminés correctement.

En réunissant tout, je mettrais en œuvre ce code comme suit:

        using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["db"].ConnectionString))
        using (var cmd = new SqlCommand(@"
                INSERT INTO MagicBoxes (OwnerID, [Key], Name, [Permissions], Active, LastUpdated) 
                OUTPUT INSERTED.Id
                VALUES (@OwnerID, @BoxKey, @BoxName, 0, 1, @Date) ", conn))
        {
            cmd.Parameters.AddRange(new[]
                {
                    new SqlParameter("@OwnerID", SqlDbType.Int).Value = OwnerID,
                    new SqlParameter("@BoxKey", SqlDbType.VarChar).Value = BoxKey, 
                    new SqlParameter("@BoxName", SqlDbType.VarChar).Value = BoxName, 
                    new SqlParameter("@Date", SqlDbType.DateTime).Value = DateTime.Now 
                });

            conn.Open();

            var id = (int)cmd.ExecuteScalar();
        }
16
Filip De Vos

Ajoutez ceci à vos paramètres

SqlParameter IDParameter = new SqlParameter("@ID",SqlDbType.Int);
IDParameter.Direction = ParameterDirection.Output;
cmd.Parameters.Add(IDParameter);

Après exécution, vous pouvez récupérer l'identifiant 

int id = (int)IDParameter.Value;
5
RemoteSojourner

Pourquoi appelez-vous pas la procédure de magasin. Transmettez les valeurs à la procédure de stockage pour obtenir les valeurs insérées et à partir du SP, renvoyez la dernière valeur de départ insérée à l'aide de SCOPE_IDENTITY(). J'espère que cette aide est disponible.

0
FIre Panda