Dapper multi insert返回插入的对象

时间:2015-11-12 20:56:18

标签: sql sql-insert dapper

使用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; }
}

这里的要点是,UserIdDateCreatedDateChanged永远不会通过对象设置,因此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);
}

但是,这只会抛出一个带有消息&#34的InvalidOperationException异常;在此上下文中不允许使用可枚举的参数序列(数组,列表等)。

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

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

什么是&#34;适当的&#34;使用Dapper插入多个对象的方法,并将完全填充的对象返回给调用者?

2 个答案:

答案 0 :(得分:4)

使用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 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

//对于大型列表,您可以使用 SqlBulkCopy 查看此链接here

答案 1 :(得分:0)

对于MySql和.Net Core 2.2,您可以执行以下操作:

public async Task<IEnumerable<T>> AddandReturn<T> (object dp, string SPName) {
            using (MySqlConnection con = new MySqlConnection (connString)) {
                using (MySqlCommand cmd = new MySqlCommand (SPName, con)) {
                    IEnumerable<T> resultList = await con.QueryAsync<T> (SPName, dp, commandType : CommandType.StoredProcedure);
                    return resultList;
                }
            }
        }

并要从mysql获取ID或对象,您的存储过程应如下所示:

declare id int default 0;
insert  into objectTable(fields...)
    values (fieldvalue...); 
    set id=last_insert_id();
    select * from objectTable where objectTableid=id;

**请注意Mysql存储过程参数名称应与.Net Core中的对象属性匹配。

希望这会帮助使用MySql存储过程和.Net Core的人