it-swarm.com.de

Wie führe ich eine Einfügung aus und schicke die eingefügte Identität mit Dapper zurück?

Wie führe ich eine Einfügung in eine Datenbank durch und gebe die eingefügte Identität mit Dapper zurück?

Ich habe so etwas ausprobiert:

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 immer noch die gleiche Ausnahmespur

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
144
ppiotrowicz

Es gibt support Eingabe-/Ausgabeparameter (einschließlich RETURN value), wenn Sie DynamicParameters verwenden, aber in diesem Fall ist die einfachere Option einfach:

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

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

KB: 2019779 , "Bei Verwendung von SCOPE_IDENTITY () und @@ IDENTITY erhalten Sie möglicherweise falsche Werte", Die OUTPUT-Klausel ist der sicherste Mechanismus:

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

Eine späte Antwort, aber hier ist eine alternative zu den SCOPE_IDENTITY() Antworten, die wir am Ende verwendet haben: OUTPUT INSERTED

Nur ID des eingefügten Objekts zurückgeben:

Sie können alle oder einige Attribute der eingefügten Zeile abrufen:

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

Eingefügtes Objekt mit ID zurückgeben:

Wenn Sie möchten, können Sie Phone und Email oder sogar die gesamte eingefügte Zeile erhalten:

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

Hiermit können Sie auch Daten von delete - oder updated -Zeilen zurückgeben. Seien Sie vorsichtig, wenn Sie Auslöser verwenden, weil:

Von OUTPUT zurückgegebene Spalten spiegeln die Daten so wider, wie sie nach dem .__ sind. Die INSERT-, UPDATE- oder DELETE-Anweisung wurde abgeschlossen, aber vor dem Auslösen von ausgeführt werden.

Bei INSTEAD OF-Triggern werden die zurückgegebenen Ergebnisse so generiert, als ob die INSERT, UPDATE oder DELETE waren tatsächlich aufgetreten, auch wenn nein Änderungen erfolgen als Ergebnis der Triggeroperation. Wenn eine Eine Anweisung, die eine OUTPUT-Klausel enthält, wird im Rumpf einer .__ verwendet. Auslöser, Tabellenaliasnamen müssen verwendet werden, um auf den eingefügten Auslöser zu verweisen und gelöschte Tabellen, um das Duplizieren von Spaltenverweisen mit der .__ zu vermeiden. INSERTED- und DELETED-Tabellen, die OUTPUT zugeordnet sind.

Mehr dazu in den Dokumenten: link

24
Tadija Bagarić

Die InvalidCastException, die Sie erhalten, ist darauf zurückzuführen, dass SCOPE_IDENTITY ein Decimal (38,0) ist.

Sie können es als int zurückgeben, indem Sie es wie folgt werfen:

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

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

Ich bin mir nicht sicher, ob es daran lag, dass ich gegen SQL 2000 arbeite oder nicht, aber ich musste dies tun, damit es funktioniert.

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

Wenn Sie Dapper.SimpleSave verwenden:

 //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));
        }
    }
0
Lodlaiden

Es gibt eine großartige Bibliothek, um Ihnen das Leben zu erleichtern. Dapper.Contrib.Extensions. Nachdem Sie dies hinzugefügt haben, können Sie einfach schreiben: 

public int Add(Transaction transaction)
{
        using (IDbConnection db = Connection)
        {
                return (int)db.Insert(transaction);
        }
}
0
Wings