【问题标题】:Avoid loading unnecessary data from db into objects (web pages)避免将不必要的数据从数据库加载到对象(网页)中
【发布时间】:2010-03-31 20:08:02
【问题描述】:

真正的新手问题来了。是否有一种标准(或好的)方法来处理不需要将数据库表包含的所有信息加载到每个关联对象中。我在考虑网页的上下文,您将只使用对象来构建单个页面,而不是使用具有更长生命周期的对象的应用程序。

例如,假设您有一个 Article 表,其中包含 id、title、author、date、summary 和 fullContents 字段。如果您只是显示一个包含文章列表及其摘要的页面,则不需要将 fullContents 加载到关联对象中。另一方面,如果您正在显示特定文章,您可能希望为该文章加载每个字段,并且可能只为其他文章加载标题(例如,显示在最近的文章侧边栏中)。

我能想到的一些技巧:

  1. 不用担心,每次都从数据库中加载所有内容。
  2. 为每个表创建几个不同的(可能是继承的)类,并根据情况创建适当的类(例如 SummaryArticle、FullArticle)。
  3. 如果不需要该字段,请使用一个类,但在创建时将未使用的属性设置为 null 并小心。
  4. 授予对象访问数据库的权限,以便他们可以按需加载某些字段。
  5. 还有别的吗?

以上所有似乎都有相当大的缺点。

我对编程很陌生,对 OOP 很陌生,对数据库也很陌生,所以我可能完全错过了这里的明显答案。 :)

【问题讨论】:

    标签: oop database


    【解决方案1】:

    (1) 不幸的是,默认情况下,加载整个对象是 ORM 所做的。这就是手动调整的 SQL 性能更好的原因。但是大多数对象不需要这种优化,您可以随时将优化延迟到以后。不要过早优化(但要编写好的 SQL/HQL 并使用好的数据库设计和索引)。但总的来说,我见过的 ORM 项目导致了很多懒惰的方法,拉取或更新的数据比需要的多。

    2) 不同的模型(实体),取决于操作。我更喜欢这个。可能会向对象域添加更多类,但对我来说,这是最干净的并且会带来更好的性能和安全性(特别是如果您正在序列化为 AJAX)。我有时使用一种模型将对象序列化到客户端,而另一种模型用于内部操作。如果你使用继承,你可以很好地做到这一点。例如 CustomerBase -> 客户。 CustomerBase 可能有一个 ID、名称和地址。客户可以扩展它以添加其他信息,甚至是密码等信息。对于列表操作(列出所有客户),您可以使用自定义查询返回 CustomerBase,但对于单个 CRUD 操作(创建/检索/更新/删除),请使用完整的客户对象。即使这样,也要小心你序列化的内容。大多数框架都有他们将序列化和不会序列化的属性的白名单。使用它们。

    3) 危险的特殊情况会导致您的系统出现错误。

    4) 对性能不利。访问数据库一次,而不是针对每个字段(BLOB 除外)。

    【讨论】:

      【解决方案2】:

      您有多种方法可以解决您的问题。

      1. 使用数据库中的存储过程删除不需要的行或列。这可以很好地工作,但会占用一些空间。
      2. 使用某种 ORM。对于 .NET,您可以使用 Entity Framework、NHibernate 或 Subsonic。 .NET 还有许多其他 ORM 工具。 Ruby 内置在 Rails 中。 Java 使用休眠。
      3. 在您的网站中编写嵌入式查询。不要忘记对它们进行参数化,否则您将向黑客敞开大门。由于 SQL 和代码的混合,此选项通常不受欢迎。此外,它最容易破坏。

      【讨论】:

        【解决方案3】:

        从您的列表中,选项 1、2 和 4 可能是最常用的选项。

        1.不用担心,每次都从数据库中加载所有内容:好吧,除非您的应用程序负载过重,或者您的表中有一些极其繁重的字段,否则使用此选项可以省去计算的麻烦出更好的东西。

        2.每个表都有几个不同的,可能是继承的类,并根据情况创建适当的类(例如 SummaryArticle、FullArticle): 这样的类通常被称为“视图模型”或类似的东西,具体取决于您的数据访问策略,您也许可以在不实际声明任何新类的情况下获取此类对象。例如,使用 Linq-2-Sql 表达式 data.Articles.Select(a => new { a .Title, a.Author }) 将为您提供具有属性 TitleAuthor 的匿名类型对象的集合。生成的 SQL 将类似于select Title, Author from Article

        4.授予对象访问数据库的权限,以便他们可以按需加载某些字段:您在此处描述的对象通常称为“代理对象”和/或它们的属性称为“延迟加载”。同样,根据您的数据访问策略,创建代理可能很难也可能很容易。例如。使用 NHibernate,您可以拥有 lazy properties,只需在映射中输入 lazy=true,代理就会自动创建。

        您的问题没有提到您现在实际上是如何将数据从数据库映射到对象,但如果您目前没有使用任何 ORM 框架,请查看NHibernateEntity Framework - 它们都是非常可靠的解决方案。

        【讨论】:

          猜你喜欢
          • 2013-12-15
          • 1970-01-01
          • 2012-08-12
          • 2017-07-27
          • 1970-01-01
          • 1970-01-01
          • 2014-12-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多