LINQ-to-SQL与存储过程?[关闭]


188

我看了一下StackOverflow上的“ LINQ初学者指南”(LINQ初学者指南),但是有一个后续问题:

我们将要启动一个新项目,其中几乎所有数据库操作都将是相当简单的数据检索(该项目的另一部分已经在写数据了)。到目前为止,我们的大多数其他项目都使用存储过程来处理此类事情。但是,如果更有意义,我想利用LINQ-to-SQL。

因此,问题是这样的:对于简单的数据检索,LINQ-to-SQL或存储的proc哪种方法更好?任何特定的赞成或反对?

谢谢。

Answers:


192

LINQ优于sproc的一些优点:

  1. 类型安全性:我认为我们都理解这一点。
  2. 抽象:对于LINQ-to-Entities尤其如此。这种抽象还允许框架添加可以轻松利用的其他改进。 PLINQ是向LINQ添加多线程支持的一个示例。最小的代码更改即可添加此支持。要做这种简单地调用sproc的数据访问代码要困难得多。
  3. 调试支持:我可以使用任何.NET调试器来调试查询。使用sproc,您将无法轻松调试SQL,并且经验很大程度上取决于数据库供应商(MS SQL Server提供了查询分析器,但通常这还不够)。
  4. 与供应商无关:LINQ可用于许多数据库,并且支持的数据库数量只会增加。由于语法或功能支持的变化(如果数据库完全支持存储过程),存储过程在数据库之间并不总是可移植的。
  5. 部署:其他人已经提到了这一点,但是部署单个程序集比部署一组sprocs要容易得多。这也与#4联系在一起。
  6. 更简单:您不必学习T-SQL进行数据访问,也不必学习调用sproc所需的数据访问API(例如ADO.NET)。这与#3和#4有关。

LINQ vs sprocs的一些缺点:

  1. 网络流量:当LINQ发送整个查询时,存储过程仅需要通过导线序列化存储过程名称和参数数据。如果查询非常复杂,这可能会变得非常糟糕。但是,LINQ的抽象允许Microsoft随着时间的推移改进它。
  2. 灵活性较差:Sproc可以充分利用数据库的功能集。LINQ在其支持方面趋于更加通用。这在任何一种语言抽象中都是常见的(例如C#与汇编器)。
  3. 重新编译:如果需要更改数据访问方式,则需要重新编译,版本化和重新部署程序集。Sproc 有时可以允许DBA调整数据访问例程,而无需重新部署任何内容。

安全性和可管理性也是人们争论的话题。

  1. 安全性:例如,您可以通过直接限制对表的访问来保护敏感数据,并将ACL放在存储过程中。但是,使用LINQ,您仍然可以限制对表的直接访问,而可以将ACL放在可更新的表视图上,以达到类似的目的(假设您的数据库支持可更新的视图)。
  2. 可管理性:使用视图还为您提供了保护您的应用程序不受架构更改(如表规范化)的好处的优点。您可以更新视图而无需更改数据访问代码。

我曾经是一个存储专家,但是我开始倾向于LINQ作为总体上更好的选择。如果在某些地方存储过程明显更好,那么我可能仍会编写一个存储过程,但可以使用LINQ访问它。:)


32
“ LINQ可用于许多数据库”,但是LINQTOSQL仅支持SQL Server。
罗素H

7
LINQ to Entities除MSSQL外还与Postgres和MySql一起使用。不能确定,但​​我想我读到有关Oracle的内容。
bbqchickenrobot

devart dotConnect有一个Oracle东西,但它的确像地狱般的越野车。同样,我也无法克服由于必须从数据库中选择数据以进行更新而导致的性能缺陷(Attach()也可以,但是相当笨拙)
Ed James

5
我在这里没有看到任何人提及代码重用。您无法在VB6或ASP或File Maker专业应用程序中重复使用linq。如果将某些内容放入数据库,则可以在任何地方重用它。我猜你可以用linq创建一个dll,但是这变得过于复杂和糟糕。添加一个可以重用的函数或存储的过程要简单得多。
MikeKulls 2012年

说到TSQL中的代码重用(1)祝您好运,尝试将存储过程的结果保存到临时表中而不求助于动态sql。(2)组织所有的proc /功能您无能为力;命名空间很快变得混乱。(3)您编写了一个功能强大的select语句,但是现在您希望用户能够选择要排序的列-在TSQL中,您可能必须使用CTE,该CTE在可以排序的每一列上执行row_number;在LINQ中,可以if在事后用一些语句解决。
备用字节,2013年

77

我通常支持将所有内容都放入存储过程中,因为DBA多年来一直在努力。对于Linq,确实很简单的CRUD查询不会有性能差异。

但是,在做出此决定时,请记住以下几点:使用任何ORM都会使您与数据模型紧密相关。在不强迫您更改编译代码的情况下,DBA不能自由更改数据模型。使用存储过程,您可以在某种程度上隐藏这些更改,因为从过程返回的参数列表和结果集代表其合同,并且只要可以遵守合同,就可以更改内部变量。 。

而且,如果将Linq用于更复杂的查询,则调整数据库将变得更加困难。当存储过程运行缓慢时,DBA可以完全将注意力集中在代码上,并且有很多选择,只是为了使合同完成后仍然可以满足合同要求。

我已经看到很多很多情况,通过更改存储过程中的模式和代码可以解决应用程序中的严重问题,而无需更改已部署的已编译代码。

Linq也许采用混合方法会更好?Linq当然可以用于调用存储过程。


9
您忽略的一项功能是安全性。使用Linq,您必须直接将表公开给应用程序。使用存储过程,您可以限制对这些proc的访问并执行您的业务需求。
NotMe

19
“ DBA没有在不强迫您更改编译代码的情况下对数据模型进行更改的自由。” 你为什么要提倡这一点?没有人应该拥有“自由”进行更改,这就是配置管理的重点。无论如何,更改都应在部署之前经过开发人员,测试人员等。
尼尔·巴恩韦尔

6
@Neil:是的,但是他不能在开发环境中进行更改,除非强迫开发人员更改代码。
亚当·罗宾逊

37
我必须说,我已经看到了很多关于紧密耦合到数据库的争论,但我实际上不确定它是否有效。除了琐碎的示例,我从未真正遇到过这样的情况:我想更改数据库,该数据库无论如何都不需要更改代码。实际上,Linq与存储的proc或参数化查询有何不同?不管您使用的是ORM还是更简单的方法,您的数据访问层仍应很好地分离和抽象。那就是让您松耦合的原因,而不是您使用的技术。Just my 2c
Simon P Stevens

7
我看到有199个存储过程是为每1个通过SP签名与应用程序屏蔽的模式更改而不必要地编写的,但是与Simon P Stevens所说的相似,SP使用中的语义更改要求应用程序更改100%的存储过程。反正时间。更不用说SP的存在只是乞求一些未来的开发者或dba将一些业务逻辑泄漏到SP中这一事实。然后再多一点。

64

Linq到Sql。

SQL Server将缓存查询计划,因此存储过程不会提高性能。

另一方面,从逻辑上讲,您的linq语句将成为应用程序的一部分并经过测试。Sproc总是有点分离,很难维护和测试。

如果我现在是从头开始开发新的应用程序,那么我只会使用Linq,而不会使用sproc。


8
我不同意您关于存储没有收益的评论。我介绍了在产品系统上访问SQL Server的一系列方法,并且使用Prepare + storage proc具有最佳效果。即使跨越相同逻辑的多个调用。不过,也许您对使用率较低的数据库是正确的。
torial

如果您是并且将来将是最熟练的数据库查询开发人员,那么请使用您最熟悉的内容。与程序代码不同,您不能说“如果给出正确的答案,请发送它”。
dkretz

5
@RussellH:.Net 3.5确实如此,他们修复了.Net 4(适用于L2S和L2E)中的问题
BlueRaja-Danny Pflughoeft 2010年

3
@Kieth并非如此!与SP相比,Linq创建的执行计划更多。调试代码有好处;但是在公司部署周期中重新编译存在问题;测试不同的ACTION查询(WHERE,ORDER BY)的灵活性。更改WHERE语句的顺序可能会导致要处理其他查询。预取 在Linq中很难做到这一点。需要具有可用于调整的数据层。SP难于维护和测试吗?如果您不习惯;但是SP对于军团和VLDB,高可用性等都是有益的!Linq用于小型项目,单独工作;去吧。
SnapJag

4
@SnapJag-没错,存储过程可以为您提供更好的粒度控制,但事实是,在99%的时间(即使在我工作的大型企业系统中),您也不需要任何其他优化。Sproc很难维护和测试您是否习惯它们-我非常习惯它们(在成为开发人员之前我是DBA),并确保针对不同表的加载的每个CRUD操作的sproc最新是一种痛苦。最佳实践(IMHO)是以最简单的方式进行编码,然后运行性能检查并仅在需要的地方进行优化。
基思2010年

40

对于基本数据检索,我会毫不犹豫地选择Linq。

自转到Linq以来,我发现了以下优点:

  1. 调试DAL从未如此简单。
  2. 架构更改时的编译时间安全性是无价的。
  3. 部署更容易,因为所有内容都被编译为DLL。不再管理部署脚本。
  4. 因为Linq可以支持查询所有实现IQueryable接口的内容,所以您无需学习新的语法就可以使用相同的语法查询XML,对象和任何其他数据源。

1
对我来说,编译时间安全是关键!
bbqchickenrobot

但是,对于部署而言,如果您所在的公司团队具有部署周期,并且存在需要迅速解决的错误,那么通过QA等进行DLL的部署可能比部署单个数据库的路径更为严格。脚本。您的优势似乎更好地代表了小型团队/项目的情况。
SnapJag

3
无需进行质量检查的SQL脚本部署在这里不一定是一件好事。

27

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


10
多么愚蠢的论点-仅使用变量即可解决您的问题。
JohnOpincar

6
@John,如果您使用验证而不是文字字符串,则无济于事,因为最后您将文字字符串发送到数据库。它可能看起来像代码中的变量,但是它将是生成的T-SQL中的字符串,该字符串将被发送到数据库。
kay.one

15
SQLMenace:根据您链接到的页面,此问题已在VS2010中解决。
Mark Byers

8
发布答案时此问题有效,但此后在VS2010中已得到解决,因此不再是问题。
Brain2000

17

我认为临LINQ的论点似乎来自没有数据库开发历史的人(通常)。

尤其是在使用诸如VS DB Pro或Team Suite之类的产品时,此处提出的许多参数都不适用,例如:

难以维护和测试:VS提供完整的语法检查,样式检查,引用和约束检查等等。它还提供完整的单元测试功能和重构工具。

LINQ无法进行真正的单元测试,因为(在我看来)它无法通过ACID测试。

在LINQ中调试更容易:为什么?VS允许从托管代码中完全介入,并对SP进行常规调试。

编译为单个DLL而不是部署脚本:VS再一次获得了成功,可以构建和部署完整的数据库或进行数据安全的增量更改。

不必通过LINQ学习TSQL:不,您不需要,但是您必须学习LINQ-好处在哪里?

我真的不认为这是一种好处。从理论上讲,能够孤立地更改某些东西听起来不错,但是仅仅因为更改满足了合同并不意味着它返回了正确的结果。为了能够确定什么是正确的结果,您需要上下文,并且可以从调用代码中获得该上下文。

嗯,松耦合的应用程序是所有优秀程序员的最终目标,因为它们确实可以提高灵活性。能够孤立地更改事物真是太棒了,而您的单元测试将确保它仍然返回适当的结果。

在所有人不高兴之前,我认为LINQ占有一席之地,并且拥有美好的未来。但是对于复杂的,数据密集型应用程序,我认为它不能代替存储过程。我是今年TechEd的MVP所回应的观点(他们将保持匿名)。

编辑:LINQ to SQL存储过程方面的事情是我仍然需要阅读更多的内容-取决于我发现我可能会改变上述的内容;)


4
学习LINQ没什么大不了的-它只是语法糖。TSQL是一种完全不同的语言。苹果和橘子。
亚当·拉瑟克

3
学习LINQ的好处在于,它与单一技术无关-查询语义可以用于XML,对象等,并且随着时间的推移会不断扩展。
Dave R.

5
同意!因此,许多人(开发人员)正在小型团队和项目中寻求“上市速度”解决方案。但是,如果使用多个团队,大型数据库,大容量,高可用性,分布式系统将开发提升到下一个公司风格的水平,那么使用LINQ将会是另一回事!我不认为您会在很长时间内修改您的意见。LINQ不适用于规模较大,有多个人员,多个团队(Dev和DBA)并且有严格的部署计划的项目/团队。
SnapJag

17

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批处理;如果有一百万行,这很受欢迎。当然,有经验的用户不会使用这种方式来完成这项工作,但重点是,以这种方式掉入很容易。


2
在C / C ++ / C#中使用指针很容易失败,这意味着它永远不应该被使用吗?
bbqchickenrobot

1
有多少中级程序员处理指针?Linq将此功能公开给任何级别的编码器,这意味着错误的风险急剧增加。
雅克

1
您正在将LINQ中的新手与高级TSQL专家进行比较。并不是一个公平的比较。我同意您的代码,LINQ通常不执行批量更新/删除。但是,我认为LINQ和SP之间的大多数性能争论都是主张,而不是基于度量
liang

12

最好的代码是没有代码,使用存储过程,您必须至少在数据库中编写一些代码,并在应用程序中编写代码才能调用它,而使用LINQ to SQL或LINQ to Entities,则不必编写任何其他代码。除了实例化上下文对象以外,其他任何LINQ查询都无法提供代码。


10

LINQ在特定于应用程序的数据库和小型企业中绝对占有一席之地。

但是,在大型企业中,中央数据库充当许多应用程序的通用数据中心,我们需要抽象。我们需要集中管理安全性并显示访问历史。我们需要能够进行影响分析:如果我为满足新的业务需求而对数据模型进行少量更改,则需要更改哪些查询以及需要重新测试哪些应用程序?视图和存储过程给了我这一点。如果LINQ能够做到所有这些并提高我们的程序员的生产力,那么我将欢迎它-有没有人有在这种环境下使用它的经验?


2
您提出了一个好观点;在这种情况下,LINQ不是替代方案。
Meta-Knight

1
您的各种应用程序都应该使用一个公共的数据访问层(当然,并非总是如此)。如果是这样,则可以对公共库进行一次更改并重新部署。您还可以使用WCF之类的东西为您处理数据访问。技术上有一个很好的抽象层,可以使用linq来访问后台数据。我猜这一切都取决于您对使用SP与Linq的需求提出的要求。
bbqchickenrobot

8

在不强迫您更改编译代码的情况下,DBA不能自由更改数据模型。使用存储过程,您可以在某种程度上隐藏这些更改,因为从过程返回的参数列表和结果集代表其合同,并且只要可以遵守合同,就可以更改内部变量。 。

我真的不认为这是一种好处。从理论上讲,能够孤立地更改某些东西听起来不错,但是仅仅因为更改满足了合同并不意味着它返回了正确的结果。为了能够确定什么是正确的结果,您需要上下文,并且可以从调用代码中获得该上下文。


7

恕我直言,RAD = LINQ,RUP =存储的过程。我曾在一家大型的《财富》 500强公司工作了很多年,在包括管理层在内的许多层次上,坦率地说,我永远不会雇用RUP开发人员来进行RAD开发。他们是如此孤立,以至于他们在该过程的其他层次上做什么的知识非常有限。在孤立的环境中,通过非常特定的入口点授予DBA对数据的控制权是有意义的,因为其他人坦率地说并不知道完成数据管理的最佳方法。

但是大型企业在发展领域的步伐缓慢而痛苦,这是极其昂贵的。有时候,您需要更快地移动以节省时间和金钱,而LINQ则提供了更多功能。

有时我认为DBA偏爱LINQ,因为他们认为LINQ威胁到他们的工作安全。但这就是野兽的本质,女士们,先生们。


3
是的,我们DBA整日等待着您,要求您将Stored Proc推入生产阶段。不必这样做会伤我们的心!
山姆

6

我认为您需要使用proc进行真正的处理。

A)用linq编写所有逻辑意味着您的数据库用处不大,因为只有您的应用程序才能使用它。

B)我仍然不相信对象建模总比关系建模好。

C)用SQL测试和开发存储过程比在任何Visual Studio环境中进行编译编辑周期要快得多。您只需编辑,按F5并按选择,即可开始比赛。

D)管理和部署存储过程比程序集更容易..您只需将文件放在服务器上,然后按F5 ...

E)Linq to sql有时在您不期望的时候仍会编写糟糕的代码。

老实说,我认为最终的目的是让MS增强t-sql,以便它可以隐式地执行linq的联接投影。例如,t-sql应该知道您是否要执行order.lineitems.part。


5

LINQ不禁止使用存储过程。我已经在LINQ-SQL和LINQ-storedproc中使用了混合模式。就个人而言,我很高兴我不必编写存储的过程.... pwet-tu。


4

此外,还有可能发生2.0回滚的问题。相信我,这件事发生在我身上几次,所以我确定它发生在别人身上。

我也同意抽象是最好的。事实是,ORM的最初目的是使RDBMS与OO概念很好地匹配。但是,如果在LINQ之前一切都很好,因为必须偏离OO概念,那么请拧入它们。概念和现实并不总是很好地融合在一起。IT中没有激进的狂热分子的空间。


3

我假设你是说Linq To Sql

对于任何CRUD命令,很容易分析存储过程与任何技术的性能。在这种情况下,两者之间的任何差异都可以忽略不计。尝试对超过100,000个选择查询的5个(简单类型)字段对象进行性能分析,以了解是否存在真正的差异。

另一方面,真正的交易突破点将是您是否愿意将业务逻辑放在数据库中,这是反对存储过程的一个问题。


1
由于影响应用程序的地方多于应用程序-数据导入,其他应用程序,直接查询等,因此不将业务逻辑放入数据库中是愚蠢的。但是,如果您不担心数据完整性,请继续。
HLGEM

3
业务逻辑不应进入数据库。它应该使用易于调试和管理的编程语言。然后可以将其作为对象在应用程序之间共享。一些规则可能在数据库中,但不在业务逻辑中。
4thSpace

3

根据专家,我将LINQ定义为摩托车,将SP定义为汽车。如果您想短途旅行并且只有很少的乘客(在这种情况下为2人),请优雅地使用LINQ。但是,如果您想旅行并拥有大乐队,我想您应该选择SP。

结论是,选择摩托车还是小汽车取决于您的路线(业务),时长(时间)和乘客(数据)。

希望能有所帮助,我可能错了。:D


1
的朋友已经骑摩托车而死:P
亚历克斯

2
人们也死于驾驶汽车。

1
是的,你错了。
阿萨德·阿里

3

倾向于LINQ的所有这些答案都主要是在讨论“易于开发”,它与编码质量差或编码的惰性无关。我只是那样而已。

一些优点或Linq,我在这里读为,易于测试,易于调试等,但是这些与最终输出或最终用户无关。这总是会给最终用户带来性能上的麻烦。将很多东西加载到内存中然后在使用LINQ时应用过滤器的意义何在?

再次使用TypeSafety,请注意“我们要小心避免错误的类型转换”,这也是我们试图通过使用linq改善的质量较差的问题。即使在那种情况下,如果数据库中的任何内容发生了变化,例如String列的大小,那么linq也需要重新编译,否则就不会是类型安全的。

尽管在使用LINQ时我们发现它很好,很甜,很有趣,但它具有使开发人员变得懒惰的剪切缺点:),并且与存储的Procs相比,它的性能差(可能更糟)是1000倍。

别再懒了。我很努力 :)


4
是否将所有内容都加载到内存中并进行过滤?Linq可以将过滤器作为查询的一部分发送到数据库,并返回过滤后的结果集。
liang

有很多人认为LINQ使用foreach循环加载所有数据并对其进行处理。错了 它只是被编译成一个sql查询,并为大多数CRUD操作提供几乎相同的性能。但是是的,这不是灵丹妙药。在某些情况下,使用T-SQL或存储的proc可能会变得更好。
这是一个陷阱

我同意两个相反的论点。但是,linq将所有过滤器发送到DBMS进行处理并不是完全正确的。有一些在内存中起作用的事物,其中之一是与众不同的。
Manish

2

对于具有单个数据访问点的简单CRUD操作,如果您对语法感到满意,请说使用LINQ。对于更复杂的逻辑,如果您精通T-SQL及其更高级的操作,则我认为sproc在性能方面更为有效。您还可以从Tuning Advisor,SQL Server Profiler,从SSMS调试查询等方面获得帮助。


2

存储过程使测试更加容易,您可以更改查询而无需触摸应用程序代码。同样在linq中,获取数据并不意味着它是正确的数据。测试数据的正确性意味着可以运行应用程序,但是使用存储过程,无需触摸应用程序即可轻松进行测试。


1

结果可以总结为

LinqToSql用于小型站点和原型。它确实节省了原型制作的时间。

Sps:通用。我可以微调查询,并始终检查ActualExecutionPlan / EstimatedExecutionPlan。



0

LINQ和SQL都有它们的位置。两者都有其缺点和优点。

有时,对于复杂的数据检索,您可能需要存储的proc。有时您可能希望其他人在Sql Server Management Studio中使用您存储的proc。

Linq to Entities非常适合快速CRUD开发。

确保您只能使用一个或另一个来构建应用程序。或者您可以将其混合。这一切都取决于您的要求。但是SQL存储的proc不会很快消失。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.