Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用Dapper执行插入并返回插入的标识?_C#_Sql Server_Dapper - Fatal编程技术网

C# 如何使用Dapper执行插入并返回插入的标识?

C# 如何使用Dapper执行插入并返回插入的标识?,c#,sql-server,dapper,C#,Sql Server,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})

如何使用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();
string sql=“DECLARE@ID int;”+
“插入[MyTable]([Stuff])值(@Stuff);”+
“选择@ID=SCOPE_IDENTITY()”;
var id=connection.Query(sql,new{Stuff=mystuff}).First();
但它不起作用

@谢谢你的回复。 我已经尝试了您的解决方案,但下面仍然有相同的异常跟踪

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
System.InvalidCastException:指定的强制转换无效
在(snip)\Dapper\SqlMapper.cs中的Dapper.SqlMapper.d_ua`1.MoveNext():第610行
位于System.Collections.Generic.List`1..ctor(IEnumerable`1集合)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
在(snip)\Dapper\SqlMapper.cs:第538行中的Dapper.SqlMapper.Query[T](IDbConnection cnn,String sql,Object param,IDbTransaction transaction,Boolean buffered,Nullable`1 commandTimeout,Nullable`1 commandType)处
在(snip)\Dapper\SqlMapper.cs:第456行中的Dapper.SqlMapper.Query[T](IDbConnection cnn,String sql,Object param)处
如果您使用
DynamicParameters
,它确实支持输入/输出参数(包括
RETURN
value),但在这种情况下,更简单的选项是:

var id=connection.QuerySingle(@)
在[MyTable]([Stuff])中插入值(@Stuff);
选择CAST(SCOPE_IDENTITY()as int)”,new{Stuff=mystuff};
请注意,在较新版本的SQL Server上,您可以使用
OUTPUT
子句:

var id=connection.QuerySingle(@)
插入到[MyTable]([Stuff])
插入的输出.Id
值(@Stuff);”,new{Stuff=mystuff});

不确定这是否是因为我在使用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();
string sql=“DECLARE@ID int;”+
“插入[MyTable]([Stuff])值(@Stuff);”+
“设置@ID=SCOPE_IDENTITY();”+
“选择@ID”;
var id=connection.Query(sql,new{Stuff=mystuff}).Single();

您得到的InvalidCastException是由于范围\u标识是一个

您可以按如下方式将其强制转换为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();
stringsql=@”
在[MyTable]([Stuff])中插入值(@Stuff);
选择CAST(SCOPE_IDENTITY()作为INT)”;
intid=connection.Query(sql,new{Stuff=mystuff}).Single();
,“使用作用域\标识()和@@IDENTITY时,可能会收到不正确的值”, 输出子句是最安全的机制:

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();
stringsql=@”
将@InsertedRows声明为表(Id int);
插入到[MyTable]([Stuff])输出Inserted.Id到@InsertedRows
价值观(@Stuff);
从@InsertedRows”中选择Id;
var id=connection.Query(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));
        }
    }
//没有安全检查
公共静态int创建(对象参数)
{
使用(SqlConnection conn=newsqlconnection(GetConnectionString()))
{
conn.Open();
conn.Create((T)参数);
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));
}
}

一个迟来的答案,但这里有一个替代
SCOPE\u IDENTITY()
答案,我们最终使用了:

仅返回插入对象的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);
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语句已完成,但在触发器之前 他们被处决了

对于INSTEAD OF触发器,将生成返回的结果,就像 插入、更新或删除实际上已经发生,即使没有 触发操作的结果是进行修改。如果 包含OUTPUT子句的语句在 触发器,必须使用表别名引用插入的触发器 并删除了表,以避免使用 插入和删除与输出关联的表


文档中有更多关于它的信息:

有一个很棒的库,可以让您的生活更轻松,Dapper.Contrib.Extensions。包括这些内容后,您可以只写:

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

我看到了sql server的答案,这里是使用事务的MySql


    Dim sql As String = "INSERT INTO Empleado (nombres, apepaterno, apematerno, direccion, colonia, cp, municipio, estado, tel, cel, correo, idrol, relojchecadorid, relojchecadorid2, `activo`,`extras`,`rfc`,`nss`,`curp`,`imagen`,sueldoXHra, IMSSCotiza, thumb) VALUES (@nombres, @apepaterno, @apematerno, @direccion, @colonia, @cp, @municipio, @estado, @tel, @cel, @correo, @idrol, @relojchecadorid, @relojchecadorid2, @activo, @extras, @rfc, @nss, @curp, @imagen,@sueldoXHra,@IMSSCotiza, @thumb)"
    
            Using connection As IDbConnection = New MySqlConnection(getConnectionString())
                connection.Open()
                Using transaction = connection.BeginTransaction
                    Dim res = connection.Execute(sql, New With {reg.nombres, reg.apepaterno, reg.apematerno, reg.direccion, reg.colonia, reg.cp, reg.municipio, reg.estado, reg.tel, reg.cel, reg.correo, reg.idrol, reg.relojchecadorid, reg.relojchecadorid2, reg.activo, reg.extras, reg.rfc, reg.nss, reg.curp, reg.imagen, reg.thumb, reg.sueldoXHra, reg.IMSSCotiza}, commandTimeout:=180, transaction:=transaction)
                    lastInsertedId = connection.ExecuteScalar("SELECT LAST_INSERT_ID();", transaction:=transaction)
                    If res > 0 Then 
transaction.Commit()
return true
end if
                    
                End Using
            End Using

我在postgres 12.3中使用.NETCore3.1。根据Tadija Bagarić的回答,我最终得出:

using (var connection = new NpgsqlConnection(AppConfig.CommentFilesConnection))
        {

            string insertUserSql = @"INSERT INTO mytable(comment_id,filename,content)
                    VALUES( @commentId, @filename, @content) returning id;";

            int newUserId = connection.QuerySingle<int>(
                                            insertUserSql,
                                            new
                                            {
                                                commentId = 1,
                                                filename = "foobar!",
                                                content = "content"
                                            }
                                            );

          


        }
使用(var连接=新的NpgsqlConnection(AppConfig.CommentFilesConnection))
{
字符串insertUserSql=@“插入mytable(注释id、文件名、内容)
返回id的值(@commentId、@filename、@content;“;
int newUserId=connection.QuerySingle(
insertUserSql,
新的
{
commentId=1,
filename=“foobar!”,
content=“content”
}
);
}

其中AppConfig是我自己的类,它只是为我的连接详细信息获取一个字符串集。这是在Startup.cs ConfigureServices方法中设置的。

@ppiotrowicz hmmm。。。。该死的SCOPEIDENTITY将返回
数值
,是吗?也许使用您的原始代码并选择@id?(这只是增加了一个演员阵容)。我将做一个记录,以确保这在将来自动工作