一尘不染

Dapper多重插入返回插入的对象

sql

使用Dapper,我想实现一个接受IEnumberable类型为的对象的方法User。现在,User看起来如下:

public class User
{
  public int UserId { get; internal set; }
  public DateTime DateCreated { get; internal set; }
  public DateTime DateChanged { get; internal set; }
  public string Username { get; set; }
}

这里的要点是UserIdDateCreated并且DateChanged永远都不能通过object设置,因此不能通过internal关键字设置。相反,数据库将填充这些值。

因为因此将对象作为插入操作的一部分进行了修改,所以我想返回另一个IEnumerable类型的对象,User但这一次填充了相应的属性。

最近,我意识到我可以让Dapper遍历User对象,IEnumerable如下所示:

public int Insert(IEnumerable<User> users)
{
  string sql = string.Format("INSERT INTO [User] (Username) VALUES (@Username)");
  return GetOpenConnection().Execute<User>(sql, users);
}

这很整洁,因为我不必写foreach自己。现在,这里的问题是Execute只会返回实际插入的行数。

因此,我尝试使用Query以下方法:

public IEnumerable<User> Insert(IEnumerable<User> users)
{
  string sql = string.Format("INSERT INTO [User] (Username) VALUES (@Username) SELECT * FROM [User] WHERE UserId = scope_identity()");
  return GetOpenConnection().Query<User>(sql, users);
}

但是,这只会引发一条InvalidOperationException异常消息:“在此上下文中不允许使用可枚举的参数序列(数组,列表等)”。

我坚持这一点。我该如何进行这项工作?

我是否必须遍历对循环体内每个对象IEnumerable执行Query的输入?这样,如果我想将所有对象插入同一事务中IDbTransaction,则该方法的参数Query将无用,User因此我必须将整个循环包装在事务中,而不是将事务传递给Query

使用Dapper插入多个对象并将完全填充的对象返回给调用者的“正确”方法是什么?


阅读 204

收藏
2021-05-16

共1个答案

一尘不染

使用Dapper.Net插入或更新对象列表,不能使用查询

 connection.Query<Object>("your_query",your_list) 
 //connection.Query<Object>: use to select IEnumrable<object> from db
 //connection.QueryMultiple: use to execut multiple query at once then read result one by one

var sql = 
@"
select * from Customers where CustomerId = @id
select * from Orders where CustomerId = @id
select * from Returns where CustomerId = @id";

using (var multi = connection.QueryMultiple(sql, new {id=selectedId}))
{
  var customer = multi.Read<Customer>().Single();
  var orders = multi.Read<Order>().ToList();
  var returns = multi.Read<Return>().ToList();
   ...
}

您应该只使用Execute进行多次插入或更新

Execute("your_query",your_list, your_transaction);

因此,如果您需要对插入的记录进行多次插入和返回ID

// **using transaction depend on your needs**

//多次插入并返回完整记录的示例

  string query = @"Insert Into _TableName ( _columns) 
                                  OUTPUT INSERTED.* 
                                values ( _parameters )"; //parameters should be same as object properties name to let dapper do correct mapping

[OUTPUT插入。*] 会返回完全插入一行ID,你可以自由返回与PROPERTYNAME星号代替任何属性 [OUTPUT
INSERTED.Id]
将返回唯一ID

//对于小清单将是一个好选择

 for (int i = 0; i < youList.Count-1; i++)
                {
                    youList[i] = DbConnection.Query<object>(query, youList[i]).FirstOrDefault();
                } // for loop is better for preformance

//对于大列表,您可以使用 SqlBulkCopy在这里查看此链接

2021-05-16