如何使用 Dapper 存储过程调用父子调用
How to call parent child call using Dapper Stored Procedure
对象结构如下
public class User{
public string Name{get;set;}
public IList<Address> Addresss {get;set;}
...
}
public class Addresss{
public string Street {get;set;}
...
}
使用 Dapper,如何编写它来检索用户和地址列表,以及如何使用存储过程调用。
正在尝试打电话,DbConnection.QueryAsync<User>("storedprocedure",param:null,commandType:CommandType.StoredProcedure)
存储过程查询如下,
Select u.*,a.* from user u join address a on u.Id = a.UserId
预期结果为用户列表,其中 User.Address // 应填充关联地址列表。
我假设你的存储过程是这样的
SELECT u.Id, u.Name, a.UserId, a.Street FROM Users u JOIN Addresses a on u.Id = a.UserId
在这种情况下,您可以调用存储过程并以这种方式设置地址列表的元素
Dictionary<int, User> users = new Dictionary<int, User();
var result = connection.Query<User, Address, User>(spName, ((u, a) =>
{
if (!users.ContainsKey(u.Id))
{
users.Add(u.Id, u);
u.Addresses = new List<Address>();
}
User k = users[b.Id];
k.Addresses.Add(a);
return u;
}, splitOn:"UserId", commandType:CommandType.StoredProcedure);
那么,这里发生了什么?。 Query 方法中的 lambda 表达式接收 Dapper 从返回的 SP 数据中提取的两个对象(一个用户和一个地址),并按照 splitOn 参数在 UserId 字段处拆分。
然后 lambda 检查字典中是否有具有该 Id 的用户,如果没有,则在不忘记初始化地址列表的情况下添加用户及其密钥。
在 if 之后,lambda 从字典中取回用户并添加地址实例,最后 returns 接收到的用户对象作为输入参数。当 Dapper 完成枚举结果时,返回 IEnumerable 和地址数据。
如果您希望只有一个用户,也许另一种方法是使用 QueryMultiple,存储过程必须 return 2 个数据表,第一个包含用户信息,第二个包含用户地址。
using (SqlConnection conn = new SqlConnection(this.DbContext.CadenaConexion))
{
using (var results = conn.QueryMultiple($"EXEC MyStoredProcedure @userId=@userId", new { userId= 123 }))
{
User user = results.ReadFirst<User>();
user.Addresses = results.Read<Address>().ToList();
return user;
}
}
存储过程查询如:
SELECT * FROM dbo.User WHERE Id = @userid
SELECT * FROM dbo.Address WHERE UserId = @userid
PS:我没有运行代码,应该不会有太大差异
对象结构如下
public class User{
public string Name{get;set;}
public IList<Address> Addresss {get;set;}
...
}
public class Addresss{
public string Street {get;set;}
...
}
使用 Dapper,如何编写它来检索用户和地址列表,以及如何使用存储过程调用。
正在尝试打电话,DbConnection.QueryAsync<User>("storedprocedure",param:null,commandType:CommandType.StoredProcedure)
存储过程查询如下,
Select u.*,a.* from user u join address a on u.Id = a.UserId
预期结果为用户列表,其中 User.Address // 应填充关联地址列表。
我假设你的存储过程是这样的
SELECT u.Id, u.Name, a.UserId, a.Street FROM Users u JOIN Addresses a on u.Id = a.UserId
在这种情况下,您可以调用存储过程并以这种方式设置地址列表的元素
Dictionary<int, User> users = new Dictionary<int, User();
var result = connection.Query<User, Address, User>(spName, ((u, a) =>
{
if (!users.ContainsKey(u.Id))
{
users.Add(u.Id, u);
u.Addresses = new List<Address>();
}
User k = users[b.Id];
k.Addresses.Add(a);
return u;
}, splitOn:"UserId", commandType:CommandType.StoredProcedure);
那么,这里发生了什么?。 Query 方法中的 lambda 表达式接收 Dapper 从返回的 SP 数据中提取的两个对象(一个用户和一个地址),并按照 splitOn 参数在 UserId 字段处拆分。
然后 lambda 检查字典中是否有具有该 Id 的用户,如果没有,则在不忘记初始化地址列表的情况下添加用户及其密钥。
在 if 之后,lambda 从字典中取回用户并添加地址实例,最后 returns 接收到的用户对象作为输入参数。当 Dapper 完成枚举结果时,返回 IEnumerable 和地址数据。
如果您希望只有一个用户,也许另一种方法是使用 QueryMultiple,存储过程必须 return 2 个数据表,第一个包含用户信息,第二个包含用户地址。
using (SqlConnection conn = new SqlConnection(this.DbContext.CadenaConexion))
{
using (var results = conn.QueryMultiple($"EXEC MyStoredProcedure @userId=@userId", new { userId= 123 }))
{
User user = results.ReadFirst<User>();
user.Addresses = results.Read<Address>().ToList();
return user;
}
}
存储过程查询如:
SELECT * FROM dbo.User WHERE Id = @userid
SELECT * FROM dbo.Address WHERE UserId = @userid
PS:我没有运行代码,应该不会有太大差异