6

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

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

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

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

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

所以这是我的问题:

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

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

  3. 你通常如何在你的项目中解决这个问题?

提前致谢。

更新:这种做法源于SELECT *被认为是一种不好的做法的概念。请参阅此讨论

4

7 回答 7

8

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

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

于 2011-03-03T05:22:23.057 回答
2

First of : great question, and about time someone asked this! :-)

Yes, the fact an ORM typically returns all columns for a database table is something you need to take into consideration when designing your systems. But as you've mentioned - there are ways around this.

The main fact for me is to be aware that this is what happens - either a SELECT * FROM dbo.YourTable, or (better) a SELECT (list of all columns) FROM dbo.YourTable.

This is not a problem when you really want the whole object and all its properties, and as long as you load a few rows, that's fine, too - the convenience beats the raw performance.

You might need to think about changing your database structures a little bit - things like:

  • maybe put large columns like BLOBs into separate tables with a 1:1 link to your base table - that way, a select on the parent tables doesn't grab all those large blobs of data

  • maybe put groups of columns that are optional, that might only show up in certain situations, into separate tables and link them - again, just to keep the base tables lean'n'mean

Also: avoid trying to "arm-wrestle" your ORM into doing bulk operations - that's just not their strong point.

And: keep an eye on performance, and try to pick an ORM that allows you to change certain operations into e.g. stored procedures - Entity Framework 4 allows this. So if the deletes are killing you - maybe you just write a Delete stored proc for that table and handle that operation differently.

于 2011-03-03T05:51:31.123 回答
1

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

于 2011-03-03T05:27:26.563 回答
1

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

NHibernate 允许您将投影添加到查询中,因此您不需要使用视图或过程来限制您的列。

于 2011-03-03T06:31:24.757 回答
0

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

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

使用 LLBLGen 和其他 ORM 的一大优势(我只是自信地谈论 LLBLGen,因为我从一开始就使用它)是数据访问的性能已经由比你更了解问题的人进行了优化平均熊。

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

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

于 2011-09-08T02:06:52.873 回答
0

您可以通过使用 Projection 和 Transformers.AliasToBean 和 DTO 来限制返回的列数,它在 Criteria API 中的外观:

.SetProjection(Projections.ProjectionList()
    .Add(Projections.Property("Id"), "Id")
    .Add(Projections.Property("PackageName"), "Caption"))
.SetResultTransformer(Transformers.AliasToBean(typeof(PackageNameDTO)));
于 2011-03-03T14:08:57.717 回答
0

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

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

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

于 2011-03-03T05:24:02.607 回答