Jak wykonać wstawienie do bazy danych i zwrócić wstawioną tożsamość z Dapper?
Próbowałem czegoś takiego:
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();
Ale to nie zadziałało.
@Marc Gravell dzięki za odpowiedź. Wypróbowałem twoje rozwiązanie, ale nadal ten sam ślad wyjątku znajduje się poniżej
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
źródło
źródło
numeric
, co? Może użyj swojego oryginalnego kodu iselect @id
? (to tylko dodaje obsadę). Zrobię notatkę, aby upewnić się, że działa to automatycznie w przyszłych eleganckich kompilacjach. Inną opcją na razie jestselect cast(SCOPE_IDENTITY() as int)
- znowu trochę brzydka. Naprawię to.scope_identity
typ zwrotu tonumeric(38,0)
. +1 naprawdę dobre znalezisko. Nigdy o tym nie myślałem i jestem pewien, że nie jestem jedyny.Query<foo>
że wstawia wartości, a następnie wybiera * gdzie id = SCOPE_IDENTITY ().Query
.Query
i pobierać pierwszą wartość ze zwróconej kolekcji, myślę, żeExecuteScalar<T>
ma to większy sens w tym przypadku, ponieważ zwykle zwracana jest co najwyżej jedna wartość.KB: 2019779 , „Możesz otrzymać niepoprawne wartości, używając SCOPE_IDENTITY () i @@ IDENTITY”, Klauzula OUTPUT jest najbezpieczniejszym mechanizmem:
źródło
An enumerable sequence of parameters (arrays, lists, etc) is not allowed in this context
Późna odpowiedź, ale tutaj jest alternatywa dla
SCOPE_IDENTITY()
odpowiedzi, których użyliśmy: OUTPUT INSERTEDZwróć tylko ID wstawionego obiektu:
Pozwala uzyskać wszystkie lub niektóre atrybuty wstawionego wiersza:
Zwróć wstawiony obiekt z ID:
Jeśli chcesz, możesz dostać,
Phone
aEmail
nawet cały wstawiony wiersz:Dzięki temu możesz również zwrócić dane usuniętych lub zaktualizowanych wierszy. Po prostu bądź ostrożny, jeśli używasz wyzwalaczy, ponieważ:
Więcej na ten temat w docs: link
źródło
Wyjątek InvalidCastException, który otrzymujesz, wynika z tego, że SCOPE_IDENTITY jest wartością dziesiętną (38,0) .
Możesz zwrócić go jako int, rzutując go w następujący sposób:
źródło
Nie jestem pewien, czy to dlatego, że pracuję przeciwko SQL 2000, czy nie, ale musiałem to zrobić, aby działał.
źródło
select cast(SCOPE_IDENTITY() as int)
?Istnieje świetna biblioteka, która ułatwi Ci życie Dapper.Contrib.Extensions. Po uwzględnieniu tego możesz po prostu napisać:
źródło
Jeśli używasz Dapper.SimpleSave:
źródło