LINQ-to-SQL vs存储过程?

时间:2008-08-18 12:37:58

标签: linq linq-to-sql stored-procedures

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

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

所以,问题是:对于简单的数据检索,哪种方法更好,LINQ-to-SQL或存储过程?任何具体的专业人士或骗子?

感谢。

23 个答案:

答案 0 :(得分:187)

LINQ优于sprocs的一些优点:

  1. 类型安全:我想我们都明白这一点。
  2. 抽象LINQ-to-Entities尤其如此。这种抽象还允许框架添加您可以轻松利用的其他改进。 PLINQ是向LINQ添加多线程支持的示例。添加此支持的代码更改很少。做这个简单调用sprocs的数据访问代码会更加困难。
  3. 调试支持:我可以使用任何.NET调试器来调试查询。使用sprocs,您无法轻松调试SQL,并且该体验主要与您的数据库供应商有关(MS SQL Server提供了查询分析器,但通常这还不够)。
  4. 供应商不可知:LINQ适用于大量数据库,支持的数据库数量只会增加。 Sprocs并不总是在数据库之间移植,因为语法或功能支持不同(如果数据库支持sprocs)。
  5. 部署:其他人已经提到过这一点,但部署单个程序集比部署一组sproc更容易。这也与#4相关联。
  6. 更容易:您不必学习T-SQL来进行数据访问,也不必学习调用sprocs所需的数据访问API(例如ADO.NET)。这与#3和#4有关。
  7. LINQ vs sprocs的一些缺点:

    1. 网络流量:当LINQ发送整个查询时,sprocs只需要通过线路序列化sproc-name和参数数据。如果查询非常复杂,这可能会非常糟糕。但是,LINQ的抽象允许微软随着时间的推移改进这一点。
    2. 不太灵活:Sprocs可以充分利用数据库的功能集。 LINQ在它的支持中往往更通用。这在任何类型的语言抽象中都很常见(例如C#与汇编程序)。
    3. 重新编译:如果需要更改数据访问方式,则需要重新编译,更新和重新部署程序集。 Sprocs可以有时允许DBA调整数据访问例程,而无需重新部署任何内容。
    4. 安全性和可管理性也是人们争论的内容。

      1. 安全性:例如,您可以通过直接限制对表的访问来保护敏感数据,并将ACL放在sprocs上。但是,使用LINQ,您仍然可以限制对表的直接访问,而是将ACL放在可更新的表视图上以实现类似的结束(假设您的数据库支持可更新视图)。
      2. 可管理性:使用视图还可以为您提供保护应用程序不受架构更改(如表格规范化)的影响。您可以更新视图,而无需更改数据访问代码。
      3. 我曾经是一个很大的家伙,但我开始倾向于将LINQ作为一般的更好的选择。如果有一些区域的sprocs显然更好,那么我可能仍然会编写一个sproc但是使用LINQ访问它。 :)

答案 1 :(得分:73)

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

但在做出这个决定时要记住一些事情:使用任何ORM将您紧密地联系到您的数据模型。 DBA无法自由更改数据模型,而无需强制更改已编译的代码。使用存储过程,您可以在一定程度上隐藏这些类型的更改,因为从过程返回的参数列表和结果集表示其合同,并且只要合同仍然满足,就可以更改内部条件。

而且,如果Linq用于更复杂的查询,调整数据库将变得更加困难。当存储过程运行缓慢时,DBA可以完全专注于代码,并且有很多选项,这样只要合同在他/她完成时仍然满意。

我见过很多很多情况,通过更改存储过程中的模式和代码来解决应用程序中的严重问题,而不会对已部署的已编译代码进行任何更改。

对Linq来说,也许一个混合方法会很好吗?当然,Linq可以用来调用存储过程。

答案 2 :(得分:64)

Linq to Sql。

Sql server将缓存查询计划,因此sprocs没有性能提升。

另一方面,您的linq语句将在逻辑上成为您的应用程序的一部分并进行测试。 Sprocs总是有点分离,难以维护和测试。

如果我现在正在从头开始研究一个新的应用程序,我会使用Linq,没有sprocs。

答案 3 :(得分:38)

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

自从搬到Linq后,我发现了以下优势:

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

答案 4 :(得分:26)

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

答案 5 :(得分:17)

我认为专业LINQ论证似乎来自那些没有数据库开发历史的人(一般而言)。

特别是如果使用VS DB Pro或Team Suite等产品,此处提出的许多参数都不适用,例如:

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

LINQ使真正的单元测试变得不可能,因为(在我看来)它没有通过ACID测试。

LINQ中的调试更容易: 为什么? VS允许从托管代码完全步入并定期调试SP。

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

不必使用LINQ学习TSQL: 不,你没有,但你必须学习LINQ - 哪里有好处?

  

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

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

在你们都感到不安之前,我认为LINQ有它的位置,并且有一个美好的未来。但对于复杂的数据密集型应用程序,我认为它不准备取代存储过程。这是我今年在TechEd的一个MVP回应的观点(他们将保持无名)。

编辑:LINQ to SQL存储过程方面的东西是我还需要阅读的内容 - 取决于我发现我可能改变我的上述dia骂;)

答案 6 :(得分:17)

LINQ是新的,有它的位置。 LINQ不是为了替代存储过程而发明的。

在这里,我将重点关注一些表现神话& CONS,仅用于“LINQ to SQL”,当然我可能完全错了; - )

(1)人们说LINQ语句可以在SQL服务器中“缓存”,因此它不会失去性能。部分正确。 “LINQ to SQL”实际上是将LINQ语法转换为TSQL语句的运行时。因此从性能角度来看,硬编码的ADO.NET SQL语句与LINQ没有区别。

(2)举一个例子,客户服务UI具有“帐户转移”功能。此函数本身可能会更新10个DB表并一次性返回一些消息。使用LINQ,您必须构建一组语句并将它们作为一个批处理发送到SQL服务器。这个翻译的LINQ-> TSQL批处理的性能很难与存储过程相匹配。原因?因为您可以使用内置的SQL分析器和执行计划工具调整存储过程中语句的最小单元,所以不能在LINQ中执行此操作。

关键是,当谈论单个DB表和一小组数据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批次;如果有数百万行,这是一个打击。当然,有经验的用户不会用这种方式来完成这项工作,但重点是,这样就很容易陷入困境。

答案 7 :(得分:12)

最好的代码是没有代码,并且对于存储过程,您必须在数据库中编写至少一些代码并在应用程序中编写代码来调用它,而使用LINQ to SQL或LINQ to Entities,您不必除了实例化上下文对象之外,还要编写除任何其他LINQ查询之外的任何其他代码。

答案 8 :(得分:10)

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

但是在一个大型企业中,中央数据库作为许多应用程序的通用数据中心,我们需要抽象。我们需要集中管理安全性并显示访问历史记录。我们需要能够进行影响分析:如果我对数据模型进行一些小改动以满足新的业务需求,需要更改哪些查询以及需要重新测试哪些应用程序?观点和存储过程给了我这个。如果LINQ可以做到这一切,并使我们的程序员更高效,我会欢迎它 - 有没有人有在这种环境中使用它的经验?

答案 9 :(得分:8)

  

DBA无权进行更改   没有强迫你的数据模型   更改已编译的代码。同   存储过程,你可以隐藏这些   从那以后,某种程度的变化   参数列表和结果集   从程序代表返回   它的合同,内脏可以   改变了,只要这样   合同仍然符合。

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

答案 10 :(得分:7)

恕我直言,RAD = LINQ,RUP =存储过程。我在一家大型财富500强公司工作了很多年,包括管理层在内的许多层面,坦率地说,我绝不会聘请RUP开发人员来开发RAD。它们是如此孤立,以至于他们对在该过程的其他层面上做什么的知识非常有限。对于孤立的环境,让DBA通过非常具体的入口点控制数据是有意义的,因为其他人坦言不知道完成数据管理的最佳方法。

但是大型企业在开发领域慢慢地移动,这是非常昂贵的。有些时候你需要更快地移动以节省时间和金钱,LINQ提供了更多功能和更多功能。

有时候我认为DBA对LINQ有偏见,因为他们觉得这会威胁到他们的工作安全。但这就是野兽,女士们,先生们的本性。

答案 11 :(得分:6)

我认为你需要使用触发器进行任何真实的操作。

A)在linq中编写所有逻辑意味着您的数据库不太有用,因为只有您的应用程序可以使用它。

B)我不相信对象建模比关系建模更好。

C)在SQL中测试和开发存储过程比任何Visual Studio环境中的编译编辑周期快得多。你只需编辑,按F5并点击选择即可参加比赛。

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

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

老实说,我认为MS的最终目的是增强t-sql,以便它可以像linq那样隐含地进行连接投影。 t-sql应该知道你是否想做order.lineitems.part,例如。

答案 12 :(得分:5)

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

答案 13 :(得分:4)

此外,还存在可能的2.0回滚问题。相信我,它发生在我身上几次,所以我确信它发生在其他人身上。

我也同意抽象是最好的。除此之外,ORM的最初目的是使RDBMS与OO概念很好地匹配。但是,如果在LINQ之前一切正常,不得不偏离OO概念,那就搞砸了。概念和现实并不总是很好地融合在一起。 IT部门没有激进狂热分子的空间。

答案 14 :(得分:3)

所有这些倾向于LINQ的答案主要是谈论开发的易用性,这或多或少与编码质量差或编码懒惰有关。我只是这样。

一些优点或Linq,我在这里读到,易于测试,易于调试等,但这些都没有连接到最终输出或最终用户。这总是会给最终用户带来性能问题。是什么意思在内存中加载很多东西,然后在使用LINQ时应用过滤器?

再次TypeSafety,谨慎的是“我们小心避免错误的类型转换”,我们试图通过使用linq改善质量。即使在这种情况下,如果数据库中有任何变化,例如字符串列的大小,然后linq需要重新编译,没有那个就不会是类型安全..我试过了。

虽然我们发现在使用LINQ时它是好的,甜的,有趣的,但是它具有使开发人员懒惰的剪切劣势:)并且与存储过程相比,它被证明是性能的1000倍(可能是最差的)

不要偷懒。我正在努力。 :)

答案 15 :(得分:3)

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

作为结论,在摩托车或汽车之间进行选择取决于您的路线(业务),长度(时间)和乘客(数据)。

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

答案 16 :(得分:3)

我假设你的意思是Linq To Sql

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

另一方面,真正的交易破坏者将是您是否愿意将业务逻辑放在数据库上,这是对存储过程的反对。

答案 17 :(得分:2)

Stored Procs vs Code(之前的讨论)

答案 18 :(得分:2)

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

答案 19 :(得分:2)

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

答案 20 :(得分:1)

结果可归纳为

LinqToSql适用于小型网站和原型。它确实为原型设计节省了时间。

Sps:Universal。我可以微调我的查询并始终检查ActualExecutionPlan / EstimatedExecutionPlan。

答案 21 :(得分:1)

Create PROCEDURE userInfoProcedure
    -- Add the parameters for the stored procedure here
    @FirstName varchar,
    @LastName varchar
AS
BEGIN

    SET NOCOUNT ON;

    -- Insert statements for procedure here
    SELECT FirstName  , LastName,Age from UserInfo where FirstName=@FirstName
    and LastName=@FirstName
END
GO

http://www.totaldotnet.com/Article/ShowArticle121_StoreProcBasic.aspx

答案 22 :(得分:0)

LINQ和SQL都有自己的位置。两者都有其缺点和优点。

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

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

当然,您只能使用其中一个构建应用。或者你可以把它混合起来。这一切都归结为您的要求。但SQL存储过程不会很快消失。