将 Dapper MultiMapper 与外部连接查询一起使用

Posted

技术标签:

【中文标题】将 Dapper MultiMapper 与外部连接查询一起使用【英文标题】:using Dapper MultiMapper with an outer join query 【发布时间】:2015-04-03 17:40:37 【问题描述】:

这是我第一次使用 Dapper,我正在努力实现以下目标

我们将域对象定义为

public class Company

    public Int64 company_id  get; set; 

    public ICollection<Brand> Brands  get; set; 

    public ICollection<CompanyConnector> CompanyConnectors  get; set; 


public class Brand

    public Int64 brand_id  get; set; 

    public Int64 company_id  get; set; 

    public string brand_name  get; set; 


public class CompanyConnector

    public Int64 company_connector_id  get; set; 

    public Int64 company_id  get; set; 

我正在尝试使用 Dapper 中的多映射器来获取公司、其所有品牌(这是可选的)和所有连接器(也是可选的)。

我有一个带有左外连接的查询

select company.*, brand.* , company_connector.*
from company 
left outer join brand on company.company_id = brand.company_id
left outer join company_connector on company.company_id=        company_connector.company_id

获取数据的代码是

var lookup = new Dictionary<Int64, Company>();
connection.Query<Company, Brand, CompanyConnector, Company>(strQuery,
(c, b, cc) =>

    Company cm;
    if (!lookup.TryGetValue(c.company_id, out cm))
    
        lookup.Add(c.company_id, cm = c);
    

    if (null != b)
    
        if (null == cm.Brands)
            cm.Brands = new List<Brand>();
        cm.Brands.Add(b);
    

    if (null != cc)
    
        if (null == cm.CompanyConnectors)
            cm.CompanyConnectors = new List<CompanyConnector>();
        cm.CompanyConnectors.Add(cc);
    

    return cm;
, splitOn: "brand_id, company_connector_id"
).AsQueryable();

由于公司有 2 个品牌和 2 个连接器 - 外连接结果为 4 行 - 因此结果对象有 4 个品牌条目和 4 个连接器条目

我可以在添加到列表之前添加这行代码来检查对象是否存在

if(!cm.Brands.Any(item => item.brand_id == b.brand_id))
cm.Brands.Add(b);

问题 - 我是否以正确的方式使用它?获得正确数量的品牌记录和连接器记录的解决方案是什么

【问题讨论】:

【参考方案1】:

据我所知,Dapper 不直接支持加载子集合,这就是为什么您有代码来进行查找、检查 null、添加值...

我刚刚在那里添加了一个检查,以查看该值是否已添加到集合中。

var lookup = new Dictionary<Int64, Company>();
connection.Query<Company, Brand, CompanyConnector, Company>(strQuery,
(c, b, cc) =>

    Company cm;
    if (!lookup.TryGetValue(c.company_id, out cm))
    
        lookup.Add(c.company_id, cm = c);
    

    if (null != b)
    
        if (null == cm.Brands)
            cm.Brands = new List<Brand>();
        if(!cm.Brands.Any(r=>r.brand_id == b.brand_id ))
            cm.Brands.Add(b);
    

    if (null != cc)
    
        if (null == cm.CompanyConnectors)
            cm.CompanyConnectors = new List<CompanyConnector>();
        if(!cm.CompanyConnectors.Any(r=>r.company_connector_id  == b.company_connector_id  ))
            cm.CompanyConnectors.Add(cc);
    

    return cm;
, splitOn: "company_id, brand_id, company_connector_id"
).AsQueryable();

可以做的另一件事是分别加载 3 个集合并将它们映射到 dapper 函数之外。

select * from company
select * from brand b join company c on c.company_id = b.company_id
select * from company_connector b join company c on c.company_id = b.company_id

【讨论】:

以上是关于将 Dapper MultiMapper 与外部连接查询一起使用的主要内容,如果未能解决你的问题,请参考以下文章

将存储过程与 Dapper 一起使用有啥缺点吗?

将 IAsyncEnumerable 与 Dapper 一起使用

将 Dapper 与 SQL Server 一起使用

将 Dapper 与返回游标的 Oracle 存储过程一起使用

将 BeginTransaction 与 Dapper.IDbConnection 一起使用的正确方法

将 JSON 从外部服务器连接到 Swift tableView