Como executo uma inserção no banco de dados e retorno a identidade inserida com o Dapper?
Eu tentei algo como isto:
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();
Mas não deu certo.
@ Marc Gravell obrigado, pela resposta. Eu tentei sua solução, mas o mesmo rastreamento de exceção ainda está abaixo
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
fonte
fonte
numeric
, não é? Talvez use seu código original eselect @id
? (isso apenas adiciona um elenco). Farei uma anotação para garantir que isso funcione automaticamente em futuras compilações dapper. Outra opção por enquanto éselect cast(SCOPE_IDENTITY() as int)
- novamente, um pouco feia. Eu vou consertar isso.scope_identity
tipo de retorno énumeric(38,0)
. Marcar com +1 uma descoberta muito boa. Nunca pensei nisso realmente e tenho certeza de que não sou o único.Query<foo>
que insira valores e selecione * where id = SCOPE_IDENTITY ().Query
.Query
e obter o primeiro valor da coleção retornada, acho queExecuteScalar<T>
faz mais sentido nesse caso, pois no máximo um valor é normalmente retornado.KB: 2019779 , "Você pode receber valores incorretos ao usar SCOPE_IDENTITY () e @@ IDENTITY". A cláusula OUTPUT é o mecanismo mais seguro:
fonte
An enumerable sequence of parameters (arrays, lists, etc) is not allowed in this context
Uma resposta tardia, mas aqui está uma alternativa às
SCOPE_IDENTITY()
respostas que acabamos usando: OUTPUT INSERTEDRetorne apenas o ID do objeto inserido:
Permite obter todos ou alguns atributos da linha inserida:
Retornar objeto inserido com o ID:
Se você quisesse, poderia obter
Phone
e /Email
ou até toda a linha inserida:Além disso, com isso, você pode retornar dados de linhas excluídas ou atualizadas . Apenas tome cuidado se você estiver usando gatilhos, porque:
Mais informações nos documentos: link
fonte
A InvalidCastException que você está recebendo deve-se ao fato de SCOPE_IDENTITY ser um decimal (38,0) .
Você pode devolvê-lo como um int, lançando-o da seguinte maneira:
fonte
Não tenho certeza se foi porque estou trabalhando com o SQL 2000 ou não, mas tive que fazer isso para fazê-lo funcionar.
fonte
select cast(SCOPE_IDENTITY() as int)
?Existe uma ótima biblioteca para facilitar sua vida Dapper.Contrib.Extensions. Depois de incluir isso, você pode simplesmente escrever:
fonte
Se você estiver usando o Dapper.SimpleSave:
fonte