2011-07-19 28 views
16

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

在附注中,当我这样做时,尽管查询被参数化(更不用提资源文件中的“拼写”警告了),但Visual Studio却向我大声说出了SQL注入的可能性。

+3

为什么你的应用程序中有查询字符串?你不应该使用存储过程,你的方法会调用存储过程吗? –

+0

这只比编写查询到你的.cs或.vb文件的硬编码稍微好一些 - 也就是说它不是很好的设计。 – Yuck

+1

不幸的是我没有使用这个应用程序的存储过程的奢侈。我还有另外一种方法可以解决这个问题吗? –

回答

9

实践落入一个范围(例如避免不想使用等),并依赖于上下文。

如果你有一个从高到低的存储过程不应该使用的命令,也不应该使用ORM,那么将你复杂的SQL存储为资源并不是什么坏习惯,因为你至少不必须在System.String中转义字符,并且您至少保持眼睛的安全。如果你的SQL本质上是动态的,那么把资源文件和文本模板机制结合起来就相当干净了。

也就是说,一般(即它看起来在大多数情况下)应该避免使用资源文件,除非在维护成本,可读性和功能方面有明显的好处。有很多干净的方法将存储过程绑定到代码上;有许多有效的ORM工具和小型数据访问层可能会做得更好。

+3

为什么一般应避免使用资源文件? – stakx

8

让SQL查询与应用程序代码分离是件好事。存储过程是这样做的正常方式,但如果这样做不可行并且必须直接使用SQL,我认为您的方法很好。使用SQL服务器的最新版本时,参数化查询会在第一次运行时进行预编译,并为SP提供类似的性能。

但是,我会建议您查看其他数据访问方法,如linq-to-sql可以自动执行SQL查询生成,并为您提供更清晰的代码界面。

+2

我的回答和另外两个没有解释得到低估。任何人都可以请指出什么是错的? –

1

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

Visual Studio抱怨,因为它看不到该值是常量,并且它始终来自可信来源。

让源文件中的SQL不再比源文件中的程序代码的其余部分“硬编码”。你为什么首先做这件事?重新使用查询?也许你应该考虑商店程序,而不是...

3

我没有看到有什么特别的“坏”这样做。这与在代码中对SQL代码进行硬编码并没有多大区别,并且与在运行时生成SQL ad-hoc的代码略有不同。

你说你正在使用参数化查询,所以你不必担心脚本注入。

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

+0

谢谢 - 我还没有研究过Linq-to-SQL。我会仔细研究一下,这听起来像是一个更好的方法。 –

+1

看着Linq-to_SQL,虽然这个想法很有意义,但它似乎是一个相当广泛的学习框架。我的需求范围远小于Linq-to-SQL能够提供的范围。话虽如此,如果没有其他事情出现,我会放弃它。 –

4

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

我要去假设没有使用Linq to SQL,Entity Framework或其他ORM工具有一些令人信服的理由?

如果你必须在你的应用程序中使用硬编码SQL,会认为它是在你的代码更优秀的内联,因为它使你的代码更易读,并为此更易于维护......

+0

那么说,并在最糟糕的情况下使用存储过程,如果你必须使用sql – Khaldoun

0

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

是的,您可以将查询保留在资源文件中。或者,为了确保项目部署后没有人与他们混淆,您可以对其进行加密并将其存储在文件中。或者更好的是,您可以对它们进行加密,然后将它们存储在数据库中,以便任何访问机器的人都不会惹上他们。但最终,我不得不问,有什么意义?只需对它们进行硬编码并完成它。

KISS。

+0

硬编码他们的问题是,它变得很少维护这种方式。 –

+0

一旦部署完成后,您可能可以做些什么来改进查询?如果可能的话,你应该使用视图。 – Richard

+2

@Richard:修复错误;)假设你直接发布应用程序,并且一个查询意外地选择了错误的字段。您只需更新查询(SP,资源文件中的SQL等),而不是重新部署应用程序。 “ – HardCode

0

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

+1

”不幸的是,我没有使用这个应用程序的存储过程的奢侈。“ –

5

资源文件definitley不是这个地方。资源文件的要点是为可以本地化(即被为其他语言/文化定义的其他资源文件所覆盖)的事物提供集中的存储库。

例如,你把一个字符串"Hello"X.resources.dll,但你也可以创建一个es-ES\X.resources.dll西班牙,其中串会说"Hola"代替—那么当你的应用程序查询的字符串,它会得到无论哪种版本与用户的操作系统配置的语言/文化相匹配。

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

+0

+1给出一个原因*为什么*使用资源文件进行SQL查询可能不合适。 – stakx

+0

在我看来是最好的答案。资源是为了别的。创建一个静态类并向其添加const成员,作为Robert Levy建议的 – Adi

3

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

优点:

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

缺点:

  • 它使代码的其余部分难以调试 - 如果有各地从数据库返回的数据有问题,我有两个地方看看。许多资源键非常相似,导致了一些有趣的wtf时刻。
  • 实际上,我从来没有更新过SQL,而没有更改其余的代码。

根据我的经验,这些好处不会与缺点叠加。

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

相关问题