Wie führe ich eine Einfügung in die Datenbank durch und gebe die eingefügte Identität mit Dapper zurück?
Ich habe so etwas versucht:
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();
Aber es hat nicht funktioniert.
@ Marc Gravell danke für die Antwort. Ich habe Ihre Lösung ausprobiert, aber die gleiche Ausnahmespur ist unten aufgeführt
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
quelle
quelle
numeric
, was? Vielleicht verwenden Sie Ihren Originalcode undselect @id
? (Dies fügt nur eine Besetzung hinzu). Ich werde eine Notiz machen, um sicherzustellen, dass dies in zukünftigen adretten Builds automatisch funktioniert. Eine andere Option für den Moment istselect cast(SCOPE_IDENTITY() as int)
- wieder ein bisschen hässlich. Ich werde das beheben.scope_identity
Rückgabetyp handeltnumeric(38,0)
. +1 ein wirklich guter Fund. Niemals wirklich und ich bin sicher, dass ich nicht der einzige bin.Query<foo>
gehe davon aus, dass Werte eingefügt werden und dann * ausgewählt wird, wobei id = SCOPE_IDENTITY ().Query
.Query
den ersten Wert aus der zurückgegebenen Sammlung zu verwenden und abzurufen, istExecuteScalar<T>
dies in diesem Fall meiner Meinung nach sinnvoller, da normalerweise höchstens ein Wert zurückgegeben wird.KB: 2019779 , "Bei Verwendung von SCOPE_IDENTITY () und @@ IDENTITY erhalten Sie möglicherweise falsche Werte." Die OUTPUT-Klausel ist der sicherste Mechanismus:
quelle
An enumerable sequence of parameters (arrays, lists, etc) is not allowed in this context
Eine späte Antwort, aber hier ist eine Alternative zu den
SCOPE_IDENTITY()
Antworten, die wir letztendlich verwendet haben: OUTPUT INSERTEDNur ID des eingefügten Objekts zurückgeben:
Sie können alle oder einige Attribute der eingefügten Zeile abrufen:
Eingefügtes Objekt mit ID zurückgeben:
Wenn Sie möchten, können Sie
Phone
undEmail
oder sogar die gesamte eingefügte Zeile erhalten:Damit können Sie auch Daten von gelöschten oder aktualisierten Zeilen zurückgeben. Seien Sie vorsichtig, wenn Sie Trigger verwenden, weil:
Mehr dazu in der Dokumentation: Link
quelle
Die InvalidCastException, die Sie erhalten, ist darauf zurückzuführen, dass SCOPE_IDENTITY eine Dezimalzahl (38,0) ist .
Sie können es als int zurückgeben, indem Sie es wie folgt umwandeln:
quelle
Ich bin mir nicht sicher, ob es daran liegt, dass ich gegen SQL 2000 arbeite oder nicht, aber ich musste dies tun, damit es funktioniert.
quelle
select cast(SCOPE_IDENTITY() as int)
?Es gibt eine großartige Bibliothek, die Ihnen das Leben erleichtert Dapper.Contrib.Extensions. Nachdem Sie dies aufgenommen haben, können Sie einfach schreiben:
quelle
Wenn Sie Dapper.SimpleSave verwenden:
quelle