Dapper 多插入返回插入的对象

Dapper multi insert returning inserted objects

使用 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 关键字。相反,数据库将填充这些值。

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

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

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

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

所以我尝试使用 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 异常消息 "An enumerable sequence of parameters (arrays, lists, etc) is not allowed in this context"。

我坚持这个。我怎样才能使这项工作?

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

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

要使用 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);

因此,如果您需要多次插入和 return 插入记录的 ID

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

//多插入和return全记录示例

  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.*] 将 return 完整插入带有 id 的行,您可以通过替换自由 return 任何 属性带有 属性name [OUTPUT INSERTED.Id] 的星号将 return 只有 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 查看此 link here

对于 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

的人有所帮助