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

到目前为止,我有:

in Code的优点:

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

存储Procs的优点:

性能 安全


当前回答

目前在这里的其他几个线程中正在讨论这个问题。我一直是存储过程的支持者,尽管有一些很好的论据支持Linq to Sql。

在代码中嵌入查询将您与数据模型紧密地结合在一起。存储过程是一种很好的契约式编程形式,这意味着DBA可以自由地更改过程中的数据模型和代码,只要存储过程的输入和输出所表示的契约得到维护。

当查询隐藏在代码中,而不是在一个易于管理的中心位置时,调优生产数据库可能会非常困难。

这里是另一个当前的讨论

其他回答

CON

我发现在存储过程中进行大量的处理会使您的DB服务器在扩展您的行为时成为一个单一的不灵活点。

然而,如果您有多个服务器运行您的代码,那么在您的程序中进行所有这些处理而不是sql-server,可能会允许您进行更多的扩展。当然,这并不适用于只进行正常获取或更新的存储procs,而是适用于执行更多处理(如在数据集上循环)的存储procs。

PROS

Performance for what it may be worth (avoids query parsing by DB driver / plan recreation etc) Data manipulation is not embedded in the C/C++/C# code which means I have less low level code to look through. SQL is less verbose and easier to look through when listed separately. Due to the separation folks are able to find and reuse SQL code much easier. Its easier to change things when schema changes - you just have to give the same output to the code and it will work just fine Easier to port to a different database. I can list individual permissions on my stored procedures and control access at that level too. I can profile my data query/ persistence code separate from my data transformation code. I can implement changeable conditions in my stored procedure and it would be easy to customize at a customer site. It becomes easier to use some automated tools to convert my schema and statements together rather than when it is embedded inside my code where I would have to hunt them down. Ensuring best practices for data access is easier when you have all your data access code inside a single file - I can check for queries that access the non performant table or that which uses a higher level of serialization or select *'s in the code etc. It becomes easier to find schema changes / data manipulation logic changes when all of it is listed in one file. It becomes easier to do search and replace edits on SQL when they are in the same place e.g. change / add transaction isolation statements for all stored procs. I and the DBA guy find that having a separate SQL file is easier / convenient when the DBA has to review my SQL stuff. Lastly you don't have to worry about SQL injection attacks because some lazy member of your team did not use parametrized queries when using embedded sqls.

目前在这里的其他几个线程中正在讨论这个问题。我一直是存储过程的支持者,尽管有一些很好的论据支持Linq to Sql。

在代码中嵌入查询将您与数据模型紧密地结合在一起。存储过程是一种很好的契约式编程形式,这意味着DBA可以自由地更改过程中的数据模型和代码,只要存储过程的输入和输出所表示的契约得到维护。

当查询隐藏在代码中,而不是在一个易于管理的中心位置时,调优生产数据库可能会非常困难。

这里是另一个当前的讨论

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

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

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

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

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

我还没有找到一种在源代码控制中轻松维护存储过程的好方法,使其与代码库一样无缝。这是不会发生的。仅这一点就使得在代码中添加SQL对我来说是值得的。在现代系统中,性能差异可以忽略不计。

对于Microsoft SQL Server,您应该尽可能使用存储过程来帮助执行计划缓存和重用。为什么要优化计划重用?因为生成执行计划的成本相当高。

Although the caching and reuse of execution plans for ad-hoc queries has improved significantly in later editions of SQL server (especially 2005 and 2008) there are still far fewer issues with plan reuse when dealing with stored procedures than there are for ad-hoc queries. For example, SQL server will only re-use an execution plan if the plan text matches exactly - right down to comments and white space, for example, if each of the following lines of SQL were to be executed independently, none of them would use the same execution plan:

SELECT MyColumn FROM MyTable WHERE id = @id
select MyColumn from MyTable WHERE id = @id
SELECT MyColumn  FROM MyTable WHERE id = @id
SELECT MyColumn FROM MyTable WHERE id = @id -- "some comment"
SELECT MyColumn FROM MyTable WHERE id = @id -- "some other comment"

除此之外,如果你不显式地指定类型的参数然后有一个好的机会,SQL Server可能出错,例如如果您执行上面的查询与输入4,然后用@ id查询SQL Server将parametrise SMALLINT(或可能是一个非常小的整数),所以如果你然后执行相同的查询@ id的说4000,SQL Server将parametrise INT,而不会重用相同的缓存。

我认为还有其他一些问题,老实说,大多数问题都可以解决——特别是在SQL Server的后续版本中,但是存储过程通常会提供更多的控制。