Как выполнить вставку и вернуть вставленный идентификатор с помощью Dapper?



Как выполнить вставку в базу данных и вернуть вставленный идентификатор с помощью Dapper?



Я пробовал что-то вроде этого:



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();


но это не сработало.



@Marc Gravell спасибо, за ответ.
Я пробовал ваше решение, но, все же же исключение трассировки ниже



System.InvalidCastException: Specified cast is not valid

at Dapper.SqlMapper.<QueryInternal>d__a`1.MoveNext() in (snip)DapperSqlMapper.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)DapperSqlMapper.cs:line 538
at Dapper.SqlMapper.Query[T](IDbConnection cnn, String sql, Object param) in (snip)DapperSqlMapper.cs:line 456
726   6  

6 ответов:

Это поддержка параметры ввода/вывода (включая RETURN значение), если вы используете DynamicParameters, но в этом случае более простой вариант просто:

string sql = @"
INSERT INTO [MyTable] ([Stuff]) VALUES (@Stuff);
SELECT CAST(SCOPE_IDENTITY() as int)";

var id = connection.Query<int>(sql, new { Stuff = mystuff}).Single();

КБ: 2019779, " вы можете получить неверные значения при использовании SCOPE_IDENTITY() и @ @ IDENTITY", Предложение OUTPUT является самым безопасным механизмом:

string sql = @"
DECLARE @InsertedRows AS TABLE (Id int);
INSERT INTO [MyTable] ([Stuff]) OUTPUT Inserted.Id INTO @InsertedRows
VALUES (@Stuff);
SELECT Id FROM @InsertedRows";

var id = connection.Query<int>(sql, new { Stuff = mystuff}).Single();

поздний ответ, но вот это альтернатива до SCOPE_IDENTITY() ответы, которые мы в конечном итоге с помощью: ВЫХОД ВСТАВЛЕН

возвращает только идентификатор вставленного объекта:

Это позволяет получить все или некоторые атрибуты вставленной строки:

string insertUserSql = @"INSERT INTO dbo.[User](Username, Phone, Email)
                        OUTPUT INSERTED.[Id]
                        VALUES(@Username, @Phone, @Email);";

int newUserId = conn.QuerySingle<int>(insertUserSql,
                                new
                                {
                                    Username = "lorem ipsum",
                                    Phone = "555-123",
                                    Email = "lorem ipsum"
                                }, tran);

возврат вставленного объекта с идентификатором:

если бы вы хотели, вы могли бы получить Phone и Email или даже весь вставлен строка:

string insertUserSql = @"INSERT INTO dbo.[User](Username, Phone, Email)
                        OUTPUT INSERTED.*
                        VALUES(@Username, @Phone, @Email);";

User newUser = conn.QuerySingle<User>(insertUserSql,
                                new
                                {
                                    Username = "lorem ipsum",
                                    Phone = "555-123",
                                    Email = "lorem ipsum"
                                }, tran);

кроме того, с этим вы можете вернуть данные удалены или обновлено строк. Просто будьте осторожны, если вы используете триггеры, потому что:

столбцы, возвращаемые из выходных данных, отражают данные, как это после Инструкция INSERT, UPDATE или DELETE завершена, но до триггеров исполняются.

для вместо триггеров, возвращаемые результаты генерируются как если бы Вставить, обновить или удалить had на самом деле произошло, даже если нет изменения происходят в результате срабатывания триггера. Если оператор, который включает предложение OUTPUT, используется внутри тела a триггер, псевдонимы таблиц должны использоваться для ссылки на вставленный триггер и deleted, чтобы избежать дублирования ссылок на столбцы Вставленные и удаленные таблицы, связанные с выводом.

подробнее об этом в документах:ссылке

InvalidCastException вы получаете из-за SCOPE_IDENTITY быть Decimal (38,0).

вы можете вернуть его как int, приведя его следующим образом:

string sql = @"
INSERT INTO [MyTable] ([Stuff]) VALUES (@Stuff);
SELECT CAST(SCOPE_IDENTITY() AS INT)";

int id = connection.Query<int>(sql, new { Stuff = mystuff}).Single();

Не уверен, что это было потому, что я работаю против SQL 2000 или нет, но я должен был сделать это, чтобы заставить его работать.

string sql = "DECLARE @ID int; " +
             "INSERT INTO [MyTable] ([Stuff]) VALUES (@Stuff); " +
             "SET @ID = SCOPE_IDENTITY(); " +
             "SELECT @ID";

var id = connection.Query<int>(sql, new { Stuff = mystuff}).Single();

Если вы используете Dapper.SimpleSave:

 //no safety checks
 public static int Create<T>(object param)
    {
        using (SqlConnection conn = new SqlConnection(GetConnectionString()))
        {
            conn.Open();
            conn.Create<T>((T)param);
            return (int) (((T)param).GetType().GetProperties().Where(
                    x => x.CustomAttributes.Where(
                        y=>y.AttributeType.GetType() == typeof(Dapper.SimpleSave.PrimaryKeyAttribute).GetType()).Count()==1).First().GetValue(param));
        }
    }

Comments

    Ничего не найдено.