LINQ-to-SQL与存储过程?
我看了一下StackOverflow上的" LINQ入门指南"(LINQ入门指南),但有一个后续问题:
我们将要启动一个新项目,其中几乎所有数据库操作都将是相当简单的数据检索(项目的另一部分已经在写数据了)。到目前为止,我们的大多数其他项目都使用存储过程来处理此类事情。但是,如果更有意义,我想利用LINQ-to-SQL。
因此,问题是这样的:对于简单的数据检索,LINQ-to-SQL或者存储的proc哪种方法更好?任何特定的赞成或者反对?
谢谢。
解决方案
回答
Linq到Sql。
SQL Server将缓存查询计划,因此存储过程不会提高性能。
另一方面,从逻辑上讲,linq语句将成为应用程序的一部分并经过测试。 Sproc总是有点分离,很难维护和测试。
如果我现在是从头开始开发新的应用程序,那么我只会使用Linq,而不会使用sproc。
回答
我假设你是说Linq To Sql
对于任何CRUD命令,很容易分析存储过程与任何技术的性能。在这种情况下,两者之间的任何差异都可以忽略不计。尝试对超过100,000个选择查询的5个(简单类型)字段对象进行性能分析,以了解是否存在真正的差异。
另一方面,真正的失败者将是我们是否愿意将业务逻辑放在数据库中,这是反对存储过程的一个问题。
回答
最好的代码是没有代码,使用存储过程,我们必须至少在数据库中编写一些代码,并在应用程序中编写代码才能调用它,而使用LINQ to SQL或者LINQ to Entities,则不必编写任何其他代码。除了实例化上下文对象外,其他任何LINQ查询之外的代码。
回答
通常,我支持将所有内容放入存储过程,因为DBA多年来一直在努力。就Linq而言,确实很简单的CRUD查询不会有性能差异。
但是,在做出此决定时请牢记一些注意事项:使用任何ORM都会使我们与数据模型紧密相关。在不强迫我们更改编译代码的情况下,DBA不能自由更改数据模型。使用存储过程,我们可以在某种程度上隐藏这些更改,因为从过程返回的参数列表和结果集代表其合同,并且只要可以遵守该合同,就可以更改内部变量。 。
而且,如果将Linq用于更复杂的查询,则调整数据库将变得更加困难。当存储过程运行缓慢时,DBA可以完全专注于隔离代码,并具有许多选择,只是为了使合同完成后仍然可以满足合同要求。
我已经看到很多很多情况,通过更改存储过程中的模式和代码可以解决应用程序中的严重问题,而无需更改已部署的已编译代码。
Linq也许采用混合方法会更好?当然,Linq可用于调用存储过程。
回答
对于基本数据检索,我会毫不犹豫地选择Linq。
自从搬到Linq以来,我发现了以下优点:
- 调试DAL从未如此简单。
- 架构更改时的编译时间安全性是无价的。
- 部署更容易,因为所有内容都被编译为DLL。不再管理部署脚本。
- 因为Linq可以支持查询所有实现IQueryable接口的内容,所以我们无需学习新的语法就可以使用相同的语法查询XML,对象和任何其他数据源。
回答
A DBA has no freedom to make changes to the data model without forcing you to change your compiled code. With stored procedures, you can hide these sorts of changes to an extent, since the parameter list and results set(s) returned from a procedure represent its contract, and the innards can be changed around, just so long as that contract is still met.
我真的不认为这是一种好处。从理论上讲,能够孤立地更改某些东西听起来不错,但是仅仅因为更改满足了合同并不意味着它会返回正确的结果。为了能够确定什么是正确的结果,我们需要上下文,并且可以从调用代码中获得该上下文。
回答
LINQ优于sproc的一些优点:
- 类型安全性:我认为我们都理解这一点。
- 抽象:对于LINQ到实体尤其如此。这种抽象还允许框架添加可以轻松利用的其他改进。 PLINQ是向LINQ添加多线程支持的一个示例。最小的代码更改即可添加此支持。要做这种简单地调用sproc的数据访问代码会更加困难。
- 调试支持:我可以使用任何.NET调试器来调试查询。使用sproc,我们将无法轻松调试SQL,并且经验很大程度上取决于数据库供应商(MS SQL Server提供了查询分析器,但通常这还不够)。
- 与供应商无关:LINQ可用于许多数据库,并且支持的数据库数量只会增加。由于语法或者功能支持的不同(如果数据库完全支持存储过程),存储过程在数据库之间并不总是可移植的。
- 部署:其他人已经提到了这一点,但是部署单个程序集比部署一组sprocs要容易得多。这也与#4联系在一起。
- 更简单:我们不必学习T-SQL进行数据访问,也不必学习调用sproc所需的数据访问API(例如ADO.NET)。这与#3和#4有关。
LINQ vs sprocs的一些缺点:
- 网络流量:sproc只需要在LINQ发送整个查询的同时,通过网络对sproc-name和参数数据进行序列化。如果查询非常复杂,这可能会变得非常糟糕。但是,LINQ的抽象允许Microsoft随着时间的推移改进它。
- 灵活性较差:Sproc可以充分利用数据库的功能集。 LINQ在其支持方面趋向于更加通用。这在任何一种语言抽象中都是很常见的(例如C#与汇编器)。
- 重新编译:如果需要更改数据访问方式,则需要重新编译,版本化和重新部署程序集。有时,Sproc可以允许DBA调整数据访问例程,而无需重新部署任何内容。
安全性和可管理性也是人们争论的话题。
- 安全性:例如,我们可以通过直接限制对表的访问来保护敏感数据,并将ACL放在存储过程中。但是,使用LINQ,我们仍然可以限制对表的直接访问,而可以将ACL放在可更新的表视图上,以达到类似的目的(假设数据库支持可更新的视图)。
- 可管理性:使用视图还为我们提供了保护应用程序不受架构更改(如表规范化)的好处的优点。我们可以更新视图而无需更改数据访问代码。
我曾经是一个存储专家,但是我开始倾向于LINQ作为一般的更好选择。如果在某些地方存储过程明显更好,那么我可能仍会编写一个存储过程,但可以使用LINQ访问它。 :)
回答
LINQ不禁止使用存储过程。我已经在LINQ-SQL和LINQ-storedproc中使用了混合模式。就个人而言,我很高兴我不必编写存储的过程.... pwet-tu。
回答
LINQ将使过程缓存膨胀
如果应用程序正在使用LINQ to SQL,并且查询涉及使用长度可能高度可变的字符串,则对于每种可能的字符串长度,SQL Server过程高速缓存将使用一个版本的查询变得肿。例如,考虑以下针对AdventureWorks2008数据库中的Person.AddressTypes表创建的非常简单的查询:
var p = from n in x.AddressTypes where n.Name == "Billing" select n; var p = from n in x.AddressTypes where n.Name == "Main Office" select n;
如果这两个查询都运行,我们将在SQL Server过程高速缓存中看到两个条目:一个与NVARCHAR(7)绑定,另一个与NVARCHAR(11)绑定。现在想象一下,如果有成百上千个不同长度的输入字符串。对于完全相同的查询,过程缓存将不必要地充满各种不同的计划。
此处更多内容:https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=363290
回答
存储过程与代码(先前的讨论)
回答
我认为临LINQ的论点似乎来自没有数据库开发历史的人(通常)。
尤其是在使用诸如VS DB Pro或者Team Suite之类的产品时,此处所做的许多论点都不适用,例如:
难以维护和测试:
VS提供了完整的语法检查,样式检查,引用和约束检查等等。它还提供完整的单元测试功能和重构工具。
LINQ无法进行真正的单元测试,因为(在我看来)它无法通过ACID测试。
在LINQ中调试更容易:
为什么? VS允许从托管代码中进行全面操作,并可以对SP进行常规调试。
编译成单个DLL而不是部署脚本:
VS再一次获得了成功,它可以构建和部署完整的数据库或者进行数据安全的增量更改。
不必通过LINQ学习TSQL:
不,我们没有,但是我们必须学习LINQ的好处在哪里?
I really don't see this as being a benefit. Being able to change something in isolation might sound good in theory, but just because the changes fulfil a contract doesn't mean it's returning the correct results. To be able to determine what the correct results are you need context and you get that context from the calling code.
嗯,松耦合的应用程序是所有优秀程序员的最终目标,因为它们确实可以提高灵活性。能够孤立地进行更改非常棒,而单元测试将确保它仍然返回适当的结果。
在所有人不高兴之前,我认为LINQ占有一席之地,并且拥有美好的未来。但是对于复杂的,数据密集型应用程序,我认为它不能代替存储过程。我是今年TechEd的MVP所回应的观点(他们将保持匿名)。
编辑:LINQ to SQL存储过程方面的事情仍然是我需要阅读的内容,具体取决于我发现我可能会改变上述的内容;
回答
LINQ在特定于应用程序的数据库和小型企业中绝对占有一席之地。
但是在一个大型企业中,中央数据库充当许多应用程序的通用数据中心,我们需要抽象。我们需要集中管理安全性并显示访问历史。我们需要能够进行影响分析:如果我为满足新的业务需求而对数据模型进行少量更改,则需要更改哪些查询以及需要重新测试哪些应用程序?视图和存储过程给了我这一点。如果LINQ能够做到所有这些并提高我们的程序员的生产力,那么我将欢迎它-是否有人在这种环境下使用过它?
回答
还存在可能的2.0回滚问题。相信我,这件事发生在我身上几次,所以我确定这件事已经发生在别人身上。
我也同意抽象是最好的。事实是,任何ORM的最初目的都是使RDBMS与OO概念很好地匹配。但是,如果在LINQ之前一切都很好,因为必须偏离OO概念,那么请拧入它们。概念和现实并不总是很好地融合在一起。 IT中没有激进的狂热分子的空间。
回答
LINQ是新的,并且拥有自己的位置。并非发明LINQ来代替存储过程。
在这里,我将仅针对" LINQ to SQL"来关注一些性能神话和缺点,当然,我可能完全错了;-)
(1)人们说LINQ语句可以在SQL Server中"缓存",因此它不会损失性能。部分正确。 " LINQ to SQL"实际上是将LINQ语法转换为TSQL语句的运行时。因此,从性能的角度来看,硬编码的ADO.NET SQL语句与LINQ没有区别。
(2)以一个示例为例,客户服务UI具有"帐户转帐"功能。此函数本身可能会更新10个DB表并一次性返回一些消息。使用LINQ,我们必须构建一组语句并将它们作为一批发送到SQL Server。转换后的LINQ-> TSQL批处理的性能几乎无法与存储过程匹配。原因?因为我们可以使用内置的SQL事件探查器和执行计划工具来调整存储过程中语句的最小单元,所以我们不能在LINQ中做到这一点。
关键是,当谈论单个数据库表和少量数据CRUD时,LINQ与SP一样快。但是对于更复杂的逻辑,存储过程的性能更可调整。
(3)" LINQ to SQL"使新手很容易引入性能猪。任何高级TSQL专家都可以告诉我们何时不使用CURSOR(基本上,在大多数情况下,我们不应该在TSQL中使用CURSOR)。有了LINQ和带有查询的迷人的" foreach"循环,对于新手来说,编写这样的代码非常容易:
foreach(Customer c in query) { c.Country = "Wonder Land"; } ctx.SubmitChanges();
我们可以看到这个简单的体面代码是如此吸引人。但实际上,.NET运行时只是将其转换为更新批处理。如果只有500行,则这是500行TSQL批处理;如果有一百万行,这很受欢迎。当然,有经验的用户不会使用这种方式来完成这项工作,但是重点是,以这种方式下降很容易。
回答
恕我直言,RAD = LINQ,RUP =存储的过程。我曾在一家大型的《财富》 500强公司工作了很多年,在包括管理层在内的许多层次上,坦率地说,我永远不会雇用RUP开发人员来进行RAD开发。他们是如此孤立,以至于他们在该过程的其他级别上做什么的知识非常有限。在孤立的环境中,通过非常特定的入口点授予DBA对数据的控制是有意义的,因为坦白地说,其他人并不知道完成数据管理的最佳方法。
但是大型企业在发展领域的步伐缓慢而痛苦,这是极其昂贵的。有时候,我们需要更快地移动以节省时间和金钱,而LINQ则提供了更多功能。
有时我认为DBA偏向LINQ,因为他们认为LINQ威胁到他们的工作安全。但这就是野兽的本质,女士们,先生们。