Comment effectuer un insert et retourner l'identité insérée avec Dapper?
comment effectuer un insert dans la base de données et retourner l'identité insérée avec Dapper?
j'ai essayé quelque chose comme ça:
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();
mais ça n'a pas marché.
@Marc Gravell merci, pour la réponse. J'ai essayé votre solution mais, toujours la même exception trace est en dessous de
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
6 réponses
Il ne support entrée/sortie paramètres (y compris les RETURN
) si vous utilisez DynamicParameters
, mais dans ce cas, l'option plus simple est tout simplement:
string sql = @"
INSERT INTO [MyTable] ([Stuff]) VALUES (@Stuff);
SELECT CAST(SCOPE_IDENTITY() as int)";
var id = connection.Query<int>(sql, new { Stuff = mystuff}).Single();
KB: 2019779 , " vous pouvez recevoir des valeurs incorrectes en utilisant SCOPE_IDENTITY () et @IDENTITY@", La clause de sortie est le mécanisme le plus sûr:
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();
une réponse tardive, mais voici une alternative à la SCOPE_IDENTITY()
réponses que nous avons fini par utiliser: sortie insérée
retour seulement ID de l'objet inséré:
il vous permet d'obtenir tous ou certains attributs de la ligne insérée:
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);
retour objet inséré avec ID:
si vous vous pouvez obtenir Phone
et Email
ou même la ligne entière insérée:
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);
aussi, avec cela vous pouvez retourner les données de supprimé ou mis à jour lignes. Faites juste attention si vous utilisez des déclencheurs parce que:
les colonnes retournées de la sortie reflètent les données telles qu'elles sont après la Insérer, mettre à jour, ou supprimer la déclaration a terminé, mais avant déclencher sont exécutées.
pour au lieu de déclencheurs, les résultats retournés sont générés comme si le INSERT, UPDATE, ou DELETE avait réellement eu lieu, même si aucune les modifications ont lieu à la suite de l'opération de déclenchement. Si un l'énoncé qui inclut une clause de sortie est utilisé à l'intérieur du corps d'un trigger, les alias de table doivent être utilisés pour référencer le trigger inséré et des tableaux supprimés pour éviter de dupliquer les références de colonne avec le INSERTED et DELETED tableaux associés à la production.
plus sur elle dans les documents: lien
L'InvalidCastException que vous obtenez est due à SCOPE_IDENTITY étant un décimal(38,0) .
vous pouvez le retourner comme un int en le moulant comme suit:
string sql = @"
INSERT INTO [MyTable] ([Stuff]) VALUES (@Stuff);
SELECT CAST(SCOPE_IDENTITY() AS INT)";
int id = connection.Query<int>(sql, new { Stuff = mystuff}).Single();
Je ne suis pas sûr que ce soit parce que je travaille contre SQL 2000 ou pas, mais je devais le faire pour que ça marche.
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();
si vous utilisez 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));
}
}