【问题标题】:Should I be concerned that ORMs, by default, return all columns?我是否应该担心 ORM 默认返回所有列?
【发布时间】:2011-03-03 05:16:58
【问题描述】:

在我使用 ORM 的有限经验(到目前为止,LLBL Gen Pro 和 Entity Framework 4)中,我注意到查询本质上会返回所有列的数据。我知道 NHibernate 是另一种流行的 ORM,我不确定这是否适用,但我认为它适用。

当然,我知道有一些解决方法:

  • 创建 SQL 视图并在视图上创建模型和映射
  • 使用存储过程并在返回的结果集上创建模型和映射

我知道坚持某些做法可以帮助缓解这种情况:

  • 确保在选择数据时合理限制行数
  • 确保您的表格不会过宽(大量列和/或大型数据类型)

所以这是我的问题:

  1. 以上做法是否足够,还是我仍应考虑寻找限制返回列数的方法?

  2. 除了我上面列出的之外,还有其他方法可以限制返回的列吗?

  3. 您通常如何在您的项目中处理此问题?

提前致谢。

更新:这种想法源于SELECT * 被认为是一种不好的做法。见this discussion

【问题讨论】:

  • 是否存在性能问题?一些框架提供更细粒度的控制,但对于大多数记录,我怀疑 查询 比提取/返回数据本身更“昂贵”(对于正常情况)——当然,使用 大型数据字段...事情开始发生变化。
  • 见我上面的更新。我一直听说SELECT * 是一种不好的做法。当然,我知道这有点不同,部分原因是即使你的表发生变化,它也会返回所有行——而 ORM 不会遇到这个问题。但另一个论点是带宽消耗,这确实适用于 ORM。
  • LLBLGen 允许您从实体中删除列。您还可以拥有同一实体的不同版本(例如完整版和“精简”版)。
  • 此外,LLBLGen 允许您使用 IncludeFields 列表或 ExcludeFields 列表。但是,您仍然可以取回所有密钥(这是有道理的)。

标签: nhibernate entity-framework orm entity-framework-4 llblgenpro


【解决方案1】:

使用几乎任何类型的 ORM 的原因之一是延迟许多较低级别的关注点并专注于业务逻辑。只要您保持连接合理且表格宽度合理,ORM 旨在让数据输入和输出变得容易,而这需要整行可用。

就个人而言,我会考虑这种过早优化等问题,直到遇到因表格宽度而陷入困境的特定情况。

【讨论】:

    【解决方案2】:

    首先:很好的问题,是时候有人问这个了! :-)

    是的,在设计系统时,ORM 通常会返回数据库表的所有列这一事实是您需要考虑的。但正如你所提到的 - 有办法解决这个问题。

    对我来说主要的事实是意识到这就是发生的事情 - SELECT * FROM dbo.YourTable,或者(更好)SELECT (list of all columns) FROM dbo.YourTable

    当您真的想要整个对象及其所有属性时,这不是问题,并且只要加载几行,也可以 - 便利胜过原始性能。

    您可能需要考虑稍微改变一下您的数据库结构 - 例如:

    • 可能会将大列(如 BLOB)放入单独的表中,并以 1:1 链接到您的基表 - 这样,父表上的选择不会抓取所有这些大数据块

    • 可能会将仅在某些情况下可能显示的可选列组放入单独的表中并将它们链接起来 - 再次,只是为了保持基表精益'n'mean

      李>

    另外:避免试图“与你的 ORM 搏斗”进行批量操作 - 这不是他们的强项。

    并且:注意性能,并尝试选择一个允许您将某些操作更改为例如的 ORM。存储过程 - Entity Framework 4 允许这样做。因此,如果删除正在杀死您 - 也许您只需为该表编写一个 Delete 存储过程并以不同方式处理该操作。

    【讨论】:

      【解决方案3】:

      问题here 很好地涵盖了您的选择。基本上,您仅限于手工制作 HQL/SQL。如果您遇到可伸缩性问题,这是您想要做的事情,但如果您这样做,它会产生非常大的积极影响。特别是,它节省了大量磁盘和网络 IO,因此您的可扩展性可以大幅提升。不过不是马上要做的事情:分析然后优化。

      【讨论】:

        【解决方案4】:

        除了我上面列出的之外,还有其他方法可以限制返回的列吗?

        NHibernate 允许您向查询添加投影,这样您就不需要使用视图或过程来限制列。

        【讨论】:

          【解决方案5】:

          对我来说,这只是一个问题,如果表有很多列 > 30,或者如果列有很多数据,例如字段中有超过 5000 个字符。

          我使用的方法是将另一个对象映射到现有表,但只包含我需要的字段。因此,对于使用 100 行填充表的搜索,我将有一个 MyObjectLite,但是当我单击查看该行的详细信息时,我会调用 GetById 并返回一个包含所有列的 MyObject。

          另一种方法是使用自定义 SQL,Stroed procs,但我认为只有在您确实需要性能提升并让用户抱怨时才应该走这条路。因此,除非存在性能问题,否则不要浪费时间尝试解决不存在的问题。

          【讨论】:

            【解决方案6】:

            您可以通过使用 Projection 和 Transformers.AliasToBean 和 DTO 来限制返回的列数,这里是 Criteria API 中的样子:

            .SetProjection(Projections.ProjectionList()
                .Add(Projections.Property("Id"), "Id")
                .Add(Projections.Property("PackageName"), "Caption"))
            .SetResultTransformer(Transformers.AliasToBean(typeof(PackageNameDTO)));
            

            【讨论】:

              【解决方案7】:

              在 LLBLGen Pro 中,您可以返回 Typed Lists,它不仅允许您定义返回哪些字段,还允许您连接数据,以便您可以从多个表中提取自定义字段列表。

              总的来说,我同意在大多数情况下,这是过早的优化。

              使用 LLBLGen 和其他 ORM 的一大优势(我对 LLBLGen 的讨论充满信心,因为我从一开始就使用它)是数据访问的性能已经由了解问题的人优化比一般的熊好。

              只要他们找到了进一步加快代码速度的方法,您只需重新生成数据层或安装新的 dll,即可“免费”获得这些更改。

              除非您认为自己是编写数据访问代码的专家,否则 ORM 可能会提高大多数开发人员的效率和准确性。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-04-08
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多