Dapper for NET Core:插入数据到表中并返回插入行的id

8

我在我的存储库中有以下方法。目前,我认为返回的 int 值只是指示操作是否成功的值。我想要这个 int 值是在操作成功执行后返回表的单列 id。我该怎么实现呢?

    public async Task<int> AddNewGroup()
    {
        using(_connection)
        {
            _connection.Open();
            var id = await _connection.ExecuteAsync("INSERT INTO groups").Single();
        }
    }
6个回答

12

您可以运行包含两部分的查询,第一部分是您的INSERT部分,第二部分是SELECT部分。在SELECT部分,您可以返回(select)想要的任何列值。

例如,如果您的组表具有名为GroupId的主键列,并且您已将该列设置为自动生成值(自动值生成),则可以调用SCOPE_IDENTITY()以获取生成的值。

我们将使用QueryAsync方法。

public async Task<int> AddNewGroup()
{
   using(_connection)
   {
      _connection.Open();
      var q = @"INSERT INTO Groups(Name,Description) VALUES
                 (@name, @desc); SELECT CAST(SCOPE_IDENTITY() as int)"
      var result = await _connection.QueryAsync<int>(q, 
                                          new { @name="some name", @desc="some desc"});
      return result.Single();
   }
}

8

不必手动创建插入查询,可以使用Dapper.Contrib来帮助管理CRUD操作。

使用Dapper.Contrib,您可以像这样进行操作:

 public async Task<int> AddNewGroup(Group entity)
 {
        using (_connection)
        {
             _connection.Open();
             var id = await _connection.InsertAsync(entity);
         }
 }

1
你知道当标识列是GUID而不是自增int时的解决方案吗? - Rajiv
2
Dapper.Contrib似乎只有返回int或long的插入方法,但如果您想要将Guid作为插入结果获得,可以通过使用_connection.QueryFirstAsync<T>(rawSql)创建自己的Insert方法,其中rawSql是带有Output的您的插入语句。例如,rawSql= "insert into users (id, username, firstname, lastname) OUTPUT Inserted.Id values(newid(), 'rajiv','raj','iv');" 您还可以使用OUTPUT获取整个插入行。 - Popa Andrei
嗨@Rajiv,为什么不在你的代码函数中生成guid并将其与其他内容一起发布并保存“往返”呢?由于guid是全局唯一的,在这种情况下是理想的。 - stan4th

3

是的。备注:OUTPUT inserted.id,其中id是您映射到键的字段名称的字段名。 - undefined

2

您可以在插入语句中使用 RETURNING id。这是使用 C# 和 Dapper。

private readonly NpgsqlConnection _connection = new NpgsqlConnection();

var sqlInsert = $""""
            INSERT INTO tabel_name (column_name)
            VALUES ('value')
            RETURNING id;
            """";

 var id = await _connection.ExecuteScalarAsync(sqlInsert);

如果你想确定返回的键类型,可以使用以下代码:

var id = await _connection.ExecuteScalarAsync<int>(sqlInsert);

在<>括号中指定类型。如果不指定,它将返回对象类型。


目前这是唯一可行的方式。 - MaxDNet

2
    public static void Main()
    {
        string sql = @"INSERT INTO Customers (CustomerName, ContactName, Address, City, PostalCode, Country) 
        Values (@CustomerName, @ContactName, @Address, @City, @PostalCode, @Country);
        SELECT CustomerID FROM Customers WHERE CustomerID = SCOPE_IDENTITY();";

        using (var connection = new SqlConnection(GetConnectionString()))
        {
            Customer c = new Customer("Brian Adams", "Brian", "12 Jones Place", "New York", "NY12", "CA");
                            
            var id = connection.QueryFirstOrDefault<int>(sql, c);
            
            Console.WriteLine("The Customer ID is " + id);
            sql = "Select * FROM CUSTOMERS WHERE CustomerID = @ID";
            
            var rc = connection.QueryFirstOrDefault<Customer>(sql, new{ @ID = id });
        }
    }
}

1
仅包含代码的答案是低质量的答案。 - Taslim Oseni

1

我采用的“正确”方法是(使用Guid Id显示存储库方法返回):

public async Task<Guid> CreateClient(ClientEntity clientModel)
    {
        const string sql = @"
        INSERT INTO dbo.Clients
            (
                ClientCode,
                Name,
                IsActive
            )
        OUTPUT Inserted.ClientId
        VALUES
            (
                @ClientCode,
                @Name,
                @IsActive
            )";

        using var dbConnection = await _databaseProvider.GetConnection();

        var result = await dbConnection.ExecuteScalarAsync(sql, new
        {
            ClientCode = clientModel.Code,
            Name = clientModel.Name,
            IsActive = clientModel.IsActive
        });

        if (result != null)
        {
            return Guid.Parse(result.ToString());
        }
        else {
            return Guid.Empty;
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接