【问题标题】:How to call parent child call using Dapper Stored Procedure如何使用 Dapper 存储过程调用父子调用
【发布时间】:2020-06-11 23:28:38
【问题描述】:

以下是对象结构。

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&lt;User&gt;("storedprocedure",param:null,commandType:CommandType.StoredProcedure)

存储过程查询如下, Select u.*,a.* from user u join address a on u.Id = a.UserId

预期结果为用户列表,其中 User.Address // 应填充相关地址列表。

【问题讨论】:

  • 您只需将存储过程名称替换为查询文本,然后将 commandType 参数设置为 CommandType.StoredProcedure
  • 所以你写了一个存储过程和call it from Dapper?我错过了什么吗?
  • 如何映射用户和地址?
  • 从上面给出的链接,它可以使用cnn.Execute("spMagicProc", p, commandType: CommandType.StoredProcedure); 来完成,但是,如何获取用户和地址的映射?是手动迭代和映射吗?
  • 你能显示你的存储过程的代码吗?这两个数据表是如何关联的?两个表上都有某种 PK FK 关系,例如 UserId 来定义哪些地址属于特定用户?

标签: c# dapper


【解决方案1】:

我假设你的存储过程是这样的

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 从字典中取回用户并添加地址实例,最后返回作为输入参数接收的 User 对象。当 Dapper 完成枚举结果时,将返回 IEnumerable 以及适当的地址数据。

【讨论】:

  • 谢谢,这是预期的结果。如果connection.QueryAsync 打电话,这也有效吗?
  • 应该,但您可以轻松测试
【解决方案2】:

如果您希望只有 1 个用户,那么另一种方法可能是使用 QueryMultiple,存储过程必须返回 2 个 DataTable,第一个带有用户信息,第二个带有用户地址。

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:我没有运行代码,应该不会变化太大

【讨论】:

  • 它的多条用户记录。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-22
  • 1970-01-01
  • 2023-03-27
  • 2017-10-08
  • 2021-12-29
相关资源
最近更新 更多