使用Dapper我想实现一个方法,它接受一个类型为User
的IEnumberable
对象。现在, 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; }
}
这里的要点是UserId
, DateCreated
和DateChanged
永远不会通过object设置,因此是internal
关键字。相反,数据库将填充这些值。
因为对象因此被修改为插入操作的一部分,所以我想返回另一个类型为User
的对象的IEnumerable
,但这次填充了相应的属性。
最近我意识到我可以让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
只返回实际插入的行数。
所以我尝试使用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
?这样,如果我想在同一个事务中插入所有User
对象,那么Query
方法的IDbTransaction
参数将毫无用处,因此我必须将整个循环包装在事务中,而不是将事务传递给Query
。
使用Dapper插入多个对象并将完全填充的对象返回给调用者的“正确”方法是什么?
要使用Dapper.Net插入或更新对象列表,您无法使用Query
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的完整插入行,您可以通过使用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 在此处查看此链接
对于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的人有所帮助