【问题标题】:Is it bad practice to store SQL queries in resource file?将 SQL 查询存储在资源文件中是不好的做法吗?
【发布时间】:2011-07-19 18:56:51
【问题描述】:

我有一个与 SQL Server 通信的 Web 应用程序。我没有对所有查询字符串进行硬编码,而是选择将它们存储在全局资源文件中。这被认为是不好的做法吗?

附带说明,当我这样做时,Visual Studio 对我大喊 SQL 注入的可能性,尽管这些查询已被参数化(更不用说资源文件中的“拼写”警告)。

【问题讨论】:

  • 为什么你的应用中有查询字符串?你不应该使用存储过程吗,你的方法会调用存储过程?
  • 这仅比将查询硬编码到您的 .cs 或 .vb 文件中稍微好一点 - 也就是说,这不是很好的设计。
  • 不幸的是,我没有为这个应用程序使用存储过程的奢侈。我还有其他方法可以解决这个问题吗?
  • 请记住,如果您不动态执行或连接结果,参数化查询仅在存储的 proc/sql 中更安全。如果您将字符串作为参数传递,然后执行 AND FOO='+@myvar 之类的操作,这仍然是个问题。不幸的是,我确实看到了这种事情。

标签: asp.net sql-server visual-studio-2010


【解决方案1】:

实践属于一个范围(例如避免偏爱使用等)并取决于上下文。

如果您有来自高层的命令,即不得使用存储过程,也不得使用 ORM,那么将复杂的 SQL 存储为资源并不是那么糟糕的做法,因为您至少没有转义 System.String 中的字符,并且您至少可以避免眼睛看到它。如果您的 SQL 本质上是动态的,那么将资源文件与文本模板机制相结合是相当干净的。

也就是说,通常(即在大多数情况下似乎)应该避免使用资源文件,除非在维护成本、可读性和功能方面有明显的好处。有很多干净的方法可以将存储过程绑定到代码;有许多称职的 ORM 工具和小型数据访问层(在今天的说法中也称为微 ORM)可能会做得更好。

【讨论】:

  • 为什么一般要避免使用资源文件?
  • 多年后...应该避免使用资源文件的原因是,有更好的方法从命令式代码执行 SQL,例如经典的 ADO.NET 参数化、微 ORM 或 ORM。从维护的角度来看,资源文件的开销更大。
  • 同意。上次我处理这种事情时(大约 3 年前),我也最终编写了内联的参数化 ADO.NET SQL 查询。资源文件感觉像是不必要的开销。 +1 也是为了花时间回复。 ;-)
【解决方案2】:

将 SQL 查询与应用程序代码分开是一件好事。存储过程是执行此操作的正常方法,但如果这不可行并且您必须直接使用 SQL,我认为您的方法很好。对于最新版本的 SQL Server 参数化查询,它们会在首次运行时进行预编译,并提供与 SP 相似的性能。

不过,我建议您研究其他数据访问方法,例如 linq-to-sql,它可以自动生成 SQL 查询并在代码中为您提供更简洁的界面。

【讨论】:

  • 我的回答和另外两个在没有解释的情况下被否决。谁能指出问题所在?
  • 有些人就是很难取悦。
【解决方案3】:

资源文件是明确的,不是这个地方。资源文件的重点是成为可以本地化的东西的集中存储库(即被为其他语言/文化定义的其他资源文件覆盖)。

例如,您可以将字符串"Hello" 放在X.resources.dll 中,但您也可以为西班牙语创建一个es-ES\X.resources.dll,其中字符串会改为"Hola" — 然后当您的应用程序查询对于字符串,它将获得与用户操作系统配置的语言/文化相匹配的任何版本。

如果您希望在不重新编译代码的情况下轻松更改 SQL,请将其放入您的 App.config 并使用 ConfigurationManager 类将其读出。如果您不想在不重新编译代码的情况下更改它,只需将其硬编码为static/conststring。也就是说,理想的当然是制作真正的存储过程。

【讨论】:

  • +1 说明为什么使用资源文件进行 SQL 查询可能不合适。
  • 我认为的最佳答案。资源用于其他用途。按照 Robert Levy 的建议,创建一个静态类并向其添加 const 成员
【解决方案4】:

我认为许多人认为硬编码 SQL 是一种不好的做法,无论它是如何存储的...... :-)

我会假设有一些令人信服的理由不使用 Linq to SQL、实体框架或其他 ORM 工具?

如果您必须在应用程序中使用硬编码 SQL,您会认为它在您的代码中内联更好,因为它使您的代码更具可读性,因此更易于维护......

【讨论】:

  • 说得好,如果你必须使用 sql,在最坏的情况下使用存储过程
【解决方案5】:

我已经使用这种模式构建了一个应用程序——在 PHP 中,而不是在 .Net 中,但原理是相同的。

好处:

  • 我可以在一个文件中轻松找到我需要的所有 SQL。这在处理数据库问题时很有帮助(应用程序的任何部分是否实际使用此表?我们有多少查询该更新表 z?)。
  • 我可以轻松更新 SQL,而无需更改其余代码。

缺点:

  • 它使其余代码更难调试 - 如果从数据库返回的数据存在问题,我必须查看两个地方。而且许多资源键非常相似,导致了一些有趣的 wtf 时刻。
  • 实际上,我从来没有在不更改其余代码的情况下更新 SQL。

根据我的经验,好处并不能抵消坏处。

顺便说一句 - 许多这些缺点也适用于存储过程。使用存储过程有一个很好的例子——但不使用它们也有一个同样好的例子。

【讨论】:

    【解决方案6】:

    我看不出这样做有什么特别“坏”的地方。它与在代码中硬编码 sql 代码并没有太大区别,仅与在运行时生成 SQL ad-hoc 略有不同。

    您说您使用的是参数化查询,因此您不必担心脚本注入。

    如果您将 sql 存储在资源文件中以遵守 DRY 原则,那么您可能希望为此目的使用某种 DAL。像实体框架 (EF) 或 Linq-to-SQL

    【讨论】:

    • 谢谢 - 我还没有研究过 Linq-to-SQL。我会研究一下,听起来这是一个更好的方法。
    • 研究了 Linq-to_SQL,虽然这个想法很有意义,但它似乎是一个非常广泛的学习框架。我需要的范围比 Linq-to-SQL 的能力范围要小得多。话虽如此,如果没有其他问题,我会试一试。
    【解决方案7】:

    这不一定是坏习惯,但如果需要打开另一个文件并找到正确的密钥,它会使您的程序更难阅读。

    Visual Studio 抱怨,因为它看不到该值是恒定的并且它始终来自受信任的来源。

    在源文件中包含 SQL 并不比在源文件中包含其余程序代码更“硬编码”。你为什么首先这样做?重复使用查询?也许您应该考虑使用存储过程...

    【讨论】:

      【解决方案8】:

      想到的是,这只是给代码增加了不必要的复杂性。

      是的,您可以将查询保存在资源文件中。或者,为了确保项目部署后没有人弄乱它们,您可以对它们进行加密并将它们存储在一个文件中。或者更好的是,您可以对它们进行加密,然后将它们存储在数据库中,这样任何有权访问机器的人都不会弄乱它们。

      但最终,我不得不问,这有什么意义?只需对它们进行硬编码并完成它。

      亲吻。

      【讨论】:

      • 对它们进行硬编码的问题在于它变得更难维护。
      • 查询部署后,您可以做些什么来改进查询?如果可能,您应该使用视图。
      • @Richard:修复错误 ;) 假设您实时发布应用程序并且一个查询意外选择了错误的字段。您可以只更新查询(SP、资源文件中的 SQL 等)而不重新部署应用程序。
      【解决方案9】:

      您可以编写存储过程并在代码中调用它们,而不是读取存储在外部某处的查询。

      【讨论】:

      • “不幸的是,我没有为这个应用程序使用存储过程的奢侈。”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-29
      • 2017-04-25
      • 2020-09-10
      • 1970-01-01
      • 2022-10-06
      • 1970-01-01
      相关资源
      最近更新 更多