Dapper로 데이터베이스에 삽입하고 삽입 된 ID를 어떻게 반환합니까?
나는 이와 같은 것을 시도했다 :
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)\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
답변
그것은 수행 지원 (를 포함하여 입력 / 출력 매개 변수를 RETURN
사용하는 경우 값을) DynamicParameters
하지만,이 경우 간단한 옵션은 간단하다 :
var id = connection.QuerySingle<int>( @"
INSERT INTO [MyTable] ([Stuff]) VALUES (@Stuff);
SELECT CAST(SCOPE_IDENTITY() as int)", new { Stuff = mystuff});
최신 버전의 SQL Server에서는 다음 OUTPUT
절을 사용할 수 있습니다 .
var id = connection.QuerySingle<int>( @"
INSERT INTO [MyTable] ([Stuff])
OUTPUT INSERTED.Id
VALUES (@Stuff);", new { Stuff = mystuff});
답변
KB : 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()
우리가 사용하여 끝낸 답변 : OUTPUT INSERTED
삽입 된 객체의 ID 만 반환합니다 :
삽입 된 행의 모든 속성 또는 일부 속성을 가져올 수 있습니다.
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);
ID가 삽입 된 객체를 반환합니다.
당신이 원하는 경우에 당신은 얻을 수 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);
또한이를 통해 삭제 되거나 업데이트 된 행의 데이터를 반환 할 수 있습니다 . 다음과 같은 이유로 트리거를 사용하는 경우주의하십시오.
OUTPUT에서 리턴 된 열은 INSERT, UPDATE 또는 DELETE 문이 완료된 후이지만 트리거가 실행되기 전의 데이터를 반영합니다.
INSTEAD OF 트리거의 경우 트리거 조작의 결과로 수정이 수행되지 않더라도 INSERT, UPDATE 또는 DELETE가 실제로 발생한 것처럼 리턴 된 결과가 생성됩니다. OUTPUT 절을 포함하는 명령문이 트리거 본문 내부에서 사용되는 경우 OUTPUT과 연관된 INSERTED 및 DELETED 테이블과 컬럼 참조가 중복되지 않도록 테이블 별명을 사용하여 삽입 및 삭제 된 트리거를 참조해야합니다.
문서에서 자세히 알아보기 : 링크
답변
SCOPE_IDENTITY가 10 진수 (38,0) 이기 때문에 InvalidCastException이 발생했습니다. 입니다.
다음과 같이 캐스팅하여 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.Contrib.Extensions. 이것을 포함하면 다음과 같이 쓸 수 있습니다.
public int Add(Transaction transaction)
{
using (IDbConnection db = Connection)
{
return (int)db.Insert(transaction);
}
}
답변
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));
}
}