Dapper multi insert返回插入的对象

ack*_*ckh 8 sql dapper sql-insert

使用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; }
}
Run Code Online (Sandbox Code Playgroud)

这里的关键在于UserId,DateCreatedDateChanged永远不会通过对象进行设置,因此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);
}
Run Code Online (Sandbox Code Playgroud)

这很整洁,因为我不必写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);
}
Run Code Online (Sandbox Code Playgroud)

但是,这只是抛出一个InvalidOperationException异常消息"在此上下文中不允许使用可枚举的参数序列(数组,列表等)".

我坚持这个.我怎样才能做到这一点?

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

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

His*_*ham 6

使用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();
   ...
} 
Run Code Online (Sandbox Code Playgroud)

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

Execute("your_query",your_list, your_transaction);
Run Code Online (Sandbox Code Playgroud)

因此,如果您需要多次插入并返回插入记录的ID

// **using transaction depend on your needs**
Run Code Online (Sandbox Code Playgroud)

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

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

[OUTPUT INSERTED。*] 将返回带有ID的完整插入行,您可以通过将星号替换为属性名[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
Run Code Online (Sandbox Code Playgroud)

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