¿Cómo realizo una inserción en la base de datos y devuelvo la identidad insertada con Dapper?
He intentado algo como esto:
string sql = "DECLARE @ID int; " +
             "INSERT INTO [MyTable] ([Stuff]) VALUES (@Stuff); " +
             "SELECT @ID = SCOPE_IDENTITY()";
var id = connection.Query<int>(sql, new { Stuff = mystuff}).First();
Pero no funcionó.
@Marc Gravell gracias, por la respuesta. He intentado su solución pero, a continuación, sigue el mismo rastro de excepción.
System.InvalidCastException: Specified cast is not valid
at Dapper.SqlMapper.<QueryInternal>d__a`1.MoveNext() in (snip)\Dapper\SqlMapper.cs:line 610
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Dapper.SqlMapper.Query[T](IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Boolean buffered, Nullable`1 commandTimeout, Nullable`1 commandType) in (snip)\Dapper\SqlMapper.cs:line 538
at Dapper.SqlMapper.Query[T](IDbConnection cnn, String sql, Object param) in (snip)\Dapper\SqlMapper.cs:line 456
                    
                        c#
                                sql-server
                                dapper
                                
                    
                    
                        ppiotrowicz
fuente
                
                
            fuente

numeric, ¿eh? Tal vez use su código original yselect @id? (esto solo agrega un reparto). Haré una nota para asegurarme de que esto funcione automáticamente en futuras compilaciones aptas. Otra opción por ahora esselect cast(SCOPE_IDENTITY() as int), de nuevo, un poco feo. Arreglaré esto.scope_identitytipo de retorno esnumeric(38,0). +1 un muy buen hallazgo. Nunca lo pensé realmente y estoy seguro de que no soy el único.Query<foo>que inserta valores y luego selecciona * donde id = SCOPE_IDENTITY ().Query.Queryy obtener el primer valor de la colección devuelta, creo queExecuteScalar<T>tiene más sentido en este caso, ya que a lo sumo normalmente se devuelve un valor.KB: 2019779 , "Puede recibir valores incorrectos al usar SCOPE_IDENTITY () y @@ IDENTITY", la cláusula OUTPUT es el mecanismo más seguro:
fuente
An enumerable sequence of parameters (arrays, lists, etc) is not allowed in this contextUna respuesta tardía, pero aquí hay una alternativa a las
SCOPE_IDENTITY()respuestas que terminamos usando: SALIDA INSERTADADevolver solo ID del objeto insertado:
Le permite obtener todos o algunos atributos de la fila insertada:
Devolver objeto insertado con ID:
Si quisieras, podrías obtener
PhoneeEmailincluso toda la fila insertada:Además, con esto puede devolver datos de filas eliminadas o actualizadas . Solo tenga cuidado si está utilizando disparadores porque (del enlace mencionado anteriormente):
Más sobre esto en los documentos: enlace
fuente
La InvalidCastException que está recibiendo se debe a que SCOPE_IDENTITY es un decimal (38,0) .
Puede devolverlo como int lanzándolo de la siguiente manera:
fuente
No estoy seguro de si fue porque estoy trabajando con SQL 2000 o no, pero tuve que hacer esto para que funcione.
fuente
select cast(SCOPE_IDENTITY() as int)?Hay una gran biblioteca para hacerte la vida más fácil Dapper.Contrib.Extensions. Después de incluir esto, simplemente puede escribir:
fuente
Si está utilizando Dapper.SimpleSave:
fuente