将SQL保存在c#源代码或Stored Procs中有哪些优点/缺点?我一直在和一个朋友讨论这个问题,我们正在做一个开源项目(c# ASP。网论坛)。目前,大多数数据库访问都是通过在c#中构建内联SQL并调用SQL Server DB来完成的。所以我在试着确定,对于这个特定的项目,哪个是最好的。

到目前为止,我有:

in Code的优点:

更容易维护-不需要运行SQL脚本来更新查询 更容易移植到另一个DB -没有pros到移植

存储Procs的优点:

性能 安全


当前回答

我更喜欢使用O/R映射器,如LLBLGen Pro。

它为您提供了相对轻松的数据库可移植性,允许您使用强类型对象用与应用程序相同的语言编写数据库访问代码,并且在我看来,允许您更灵活地处理所拉回的数据。

实际上,能够使用强类型对象是使用O/R Mapper的充分理由。

其他回答

程序员希望代码在他们的应用程序中,DBA希望它在数据库中。

如果你两者都有,你可以通过使用存储过程在两者之间分配工作,程序员不必担心所有这些表如何连接在一起等(对不起,我知道你想控制一切。)

我们有一个第三方应用程序,它允许在数据库中的视图或存储过程上创建自定义报告。如果我把代码中的所有逻辑都放在另一个应用程序中,就不能重用它。如果你使用数据库编写所有的应用程序,这不是问题。

当存储过程被用于应用程序和数据库之间时,它们是最糟糕的。上面提到的使用它们的许多原因都可以由视图更好地处理。

有关安全的论点是站不住脚的。它只是将安全问题从应用程序转移到数据库。代码就是代码。我曾见过一些存储过程从应用程序中获取SQL,并使用它构建容易受到SQL注入攻击的查询。

一般来说,它们往往会在所谓的数据库开发人员和所谓的应用程序开发人员之间造成裂痕。实际上,所有编写的代码都是应用程序代码,只是执行上下文的不同。

使用丰富的SQL生成库,如LINQ, Rails ActiveRecord或Hibernate/NHibernate,使开发更快。在混合中插入存储过程会降低速度。

我在其他答案中没有发现的一点是:

如果在您的环境中,数据库及其模式是体系结构的核心,应用程序的作用更小,那么更多地使用存储过程可能是有意义的,这可能有助于为所有需要访问DB的应用程序提供一个级别基础,从而减少代码重复(例如,您确定所有访问DB的应用程序都是用c#或其他。net语言编写的吗?)

另一方面,如果应用程序具有更核心的角色,而DB更多地充当应用程序的备份存储,那么减少存储过程的使用并通过提供一个公共持久性层(可能基于ORM工具/框架)来减少代码重复可能是明智的。

在这两种情况下,重要的是不要将DB视为存储过程的方便存储库。将它们保存在版本控制系统的源文件中,并尽可能地尝试自动化它们的部署(这实际上对所有与模式相关的构件都有效)。

存储过程比代码更容易在数据库和源代码控制系统之间失去同步。应用程序代码也可以,但当您进行持续集成时,这种可能性较小。

数据库就是这样,人们不可避免地对生产数据库进行更改,只是为了暂时摆脱困境。然后忘记在环境和源代码控制系统之间同步它。生产数据库迟早会成为事实上的记录,而不是源代码控制系统——您将陷入无法删除任何scprocs的情况,因为您不知道它是否正在被使用。

一个好的过程应该只允许通过适当的渠道对产品进行更改,这样您就能够从源代码控制系统(无数据)从头开始重新构建数据库。但我只是说,因为它可以完成,也确实完成了——在最激烈的时刻,在大喊大叫的客户的电话之间,在紧盯着你的经理的电话之间,等等,对生产数据库进行了更改。

使用存储过程运行特别查询很尴尬——使用动态sql(或ORM)更容易,这可能是我自己使用存储过程的最大缺点。

另一方面,存储过程在你做出更改但不需要重新部署应用程序代码的情况下很好。它还允许您在通过网络发送数据之前对数据进行塑形,而代码中的sql可能必须进行多次调用来检索而不是塑形(尽管现在有方法可以在一次“调用”中运行多个sql语句并返回多个结果集,如ADO.NET中的MARS),这可能会导致更多的数据通过网络传输。

不过,我不相信任何关于性能和安全性的争论。两者都有可能是好的,也有可能是坏的,而且同样可控。

in Code的优点: 更容易维护-不需要运行SQL脚本来更新查询 更容易移植到另一个DB -没有pros到移植

实际上,我觉得你搞反了。恕我直言,在代码中维护SQL是痛苦的,因为:

你最终会在相关的代码块中重复自己 许多IDE不支持SQL作为一种语言,因此您只有一系列未出错的检查字符串来执行任务 数据类型、表名或约束的更改远比将整个数据库交换为一个新的数据库普遍得多 随着查询复杂性的增加,您的难度级别也在增加 测试内联查询需要构建项目

把Stored Procs看作你从数据库对象中调用的方法——它们更容易重用,只有一个地方可以编辑,而且如果你确实更改了数据库提供程序,更改发生在你的Stored Procs中,而不是在你的代码中。

也就是说,存储过程的性能增益是最小的,正如Stu在我之前说过的,你不能在存储过程中设置断点(目前)。