没有自定义 SQL 的 Dapper 中的多重映射

Posted

技术标签:

【中文标题】没有自定义 SQL 的 Dapper 中的多重映射【英文标题】:Multimapping in Dapper Without Custom SQL 【发布时间】:2016-11-14 18:53:34 【问题描述】:

有没有办法以通用方式在 Dapper 中使用多重映射,而不使用嵌入在 C# 代码中的自定义 SQL?

例如看 Correct use of Multimapping in Dapper

是否有一种通用的方法来查询来自 2 个相关实体的数据,其中公共字段会自动确定以进行连接?

【问题讨论】:

【参考方案1】:

不要这样做。千万不要这样想!数据库是持久的和规范化的。对象是易腐烂的并且经常是非规范化的,当您编写 SQL 时,在两者之间进行转换是一件需要深思熟虑的事情。这真的不是自动化的步骤。漫长而痛苦的经历使我们中的许多人相信,数据库抽象(表和连接)不应该仅仅被吸入(或生成)代码。如果您还不确定,请使用已建立的 ORM。

另一方面,如果您绝对想控制您的 SQL,但它在 C# 中的字符串文字中的“嵌入”会困扰您,那么我完全同意。我可以建议QueryFirst,这是一个为您的查询生成 C# 包装器的 Visual Studio 扩展。您的 SQL 保留在一个真实的 SQL 文件中,经过语法验证,检查了数据库引用,并且在每次保存时,QueryFirst 都会生成一个带有 Execute() 方法的包装类,并为结果生成一个 POCO。

通过多重映射,我假设您想填充嵌套对象的图形。一个很好的方法是在图形中为每个类使用一个 QueryFirst .sql,然后在父类的部分类中,添加一个 List 的子类。 (QueryFirst 生成的 POCO 分为 2 个部分类,您控制其中一个,该工具生成另一个。)

因此,对于客户及其订单的图表... 在父sql中

select * from customers where name like @custName

子sql

select * from orders where customerId = @customerId

在父部分类中,用于预加载...

    public List<Orders> orders;
    public void OnLoad()
    
        orders = new getOrders().Execute(customerId); // property of the parent POCO
    

或用于延迟加载...

    private List<Orders> _orders;
    public List<Orders> orders
    
        get
                        
            return _orders ?? _orders = new GetOrders().Execute(customerId);                
        
    

5 行代码,不包括括号,并且您有一个嵌套图,可以根据需要延迟加载或急切加载,该接口可在代码中发现(输入参数和结果的智能感知)。它们可能是这些表中的数百个列,您永远不需要重新键入它们的名称,并且它们的数据类型将透明地流入您的 C#。

清晰的职责分离。全面控制。免责声明:我写了 QueryFirst :-)

【讨论】:

谨慎使用急切加载。如果您让 QueryFirst 管理您的连接,您的父结果集将被转换为一个列表,整个结果集将被实例化,如果您有所有子结果集,可能还有它们的子元素。管理您自己的连接,因此您可以一次处理一行,然后忘记它,或者确保您的急切加载仅深入 1 级,或者您的结果集很小,可能是分页的。 QueryFirst 的整个想法是我们不应该将整个数据库放入内存中,而我刚刚为您提供了执行此操作的密钥!【参考方案2】:

使用 Dapper 进行多重映射是一种同时运行多个 SQL 查询然后返回映射到特定对象的每个结果的方法。

在这个问题的上下文中,Multimapping 甚至不相关,回复:您正在寻求一种方法来自动从给定对象生成 SQL 查询并创建正确的连接,这将导致单个 SQL 查询是与多重映射无关。

我怀疑您要查找的内容与实体框架类似。您可能想要研究几个 Dapper 扩展项目,它们会生成一些 SQL。见:Dapper.Rainbow VS Dapper.Contrib

【讨论】:

限制是不能使用EF! @Miha 我不确定您对 Dapper 的熟悉程度,但要克服 Dapper 不生成 SQL 的事实,最简单的方法是了解 Dapper 只不过是一个类型映射器(ORM 是具有误导性,因为该术语现在通常也意味着生成 SQL)。所谓 Type Mapper,我的意思是它只会将 SQL 结果的字段映射到 Type 的属性。 非常感谢 Metro Smurf 澄清概念并帮助我理解 Dapper 作为类型映射器而不是 ORM 的局限性。我正在尝试熟悉 Dapper,因为在我的情况下需要使用它。

以上是关于没有自定义 SQL 的 Dapper 中的多重映射的主要内容,如果未能解决你的问题,请参考以下文章

Dapper 多重映射 - 集合为空

将 Dapper 查询映射到对象集合(它本身有几个集合)

使用 Dapper 扩展自定义 SQL

Dapper - 如何将记录作为自定义对象类型返回?

未调用 Dapper 自定义 SqlMapper.TypeHandler Parse 方法

Dapper学习 - Dapper的基本用法