LINQ到SQL与存储过程?

我在“StackOverflow”( “LINQ初学者指南” )这篇文章中看了一下“LINQ 入门指南” ,但有一个后续问题:

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

所以,问题是这样的:对于简单的数据检索,哪种方法更好,LINQ到SQL或存储过程? 任何具体的赞成或反对?

谢谢。

LINQ over sprocs的一些优点:

  1. types安全 :我想我们都明白这一点。
  2. 抽象 : LINQ-to-Entities尤其如此。 这个抽象还允许框架添加额外的改进,您可以轻松地利用。 PLINQ是向LINQ添加multithreading支持的一个例子。 代码更改很less添加此支持。 做这个简单地调用sprocs的数据访问代码将会更加困难。
  3. debugging支持 :我可以使用任何.NETdebugging器来debugging查询。 使用sprocs,您不能轻松debuggingSQL,而且体验主要与您的数据库供应商相关联(MS SQL Server提供了查询分析器,但通常这还不够)。
  4. 供应商不可知论者 :LINQ与许多数据库一起工作,支持的数据库数量只会增加。 Sprocs并不总是可以在数据库之间移植,因为语法或function支持不同(如果数据库支持sprocs的话)。
  5. 部署 :其他人已经提到了这一点,但部署单个程序集比部署一组sprocs更容易。 这也与#4有关系。
  6. 更简单 :您不必学习T-SQL来进行数据访问,也不必学习调用sprocs所需的数据访问API(例如ADO.NET)。 这与#3和#4有关。

LINQ与sprocs的一些缺点:

  1. networkingstream量 :sprocs只需要在LINQ发送整个查询时通过线路序列化sproc-name和argument数据。 如果查询非常复杂,这可能会变得非常糟糕。 但是,LINQ的抽象允许微软随着时间的推移而改进。
  2. 不太灵活 :Sprocs可以充分利用数据库的特性。 LINQ在支持方面往往更为通用。 这在任何types的语言抽象中都很常见(例如C#vs汇编程序)。
  3. 重新编译 :如果您需要对数据访问方式进行更改,则需要重新编译,编译并重新部署您的程序集。 Sprocs 有时可以让DBA调整数据访问例程,而不需要重新部署任何东西。

安全性和易pipe理性也是人们争论的话题。

  1. 安全性 :例如,您可以通过限制直接访问表来保护敏感数据,并将ACL放在sprocs上。 但是,使用LINQ,仍然可以限制对表的直接访问,而将ACL放在可更新的表视图上,以实现类似的结果(假设您的数据库支持可更新的视图)。
  2. 可pipe理性 :使用视图还可以使您的应用程序不受模式更改的影响(如表格规范化)。 您可以更新视图,而不需要更改数据访问代码。

我曾经是一个大杂烩的家伙,但我开始倾向于LINQ作为一个更好的select。 如果有一些区域sprocs显然更好,那么我可能还会写一个sproc,但使用LINQ访问它。 🙂

我一般都是把所有东西放在存储过程中的支持者,因为DBA多年来一直在这样做。 在Linq的情况下,确实与简单的CRUD查询没有性能差异。

但在做出这个决定时请记住一些事情:使用任何ORM将您紧密地连接到您的数据模型。 DBA没有自由地修改数据模型而不强迫你改变你的编译代码。 使用存储过程,您可以在某种程度上隐藏这些types的更改,因为从过程返回的参数列表和结果集代表其合同,并且只要该合同仍然得到满足,内部程序就可以改变。

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

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

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

Linq to Sql。

Sql服务器将caching查询计划,所以sprocs没有性能增益。

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

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

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

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

  1. debugging我的DAL从未如此简单。
  2. 当你的模式改变是无价的时候编译时间安全。
  3. 部署更容易,因为所有东西都编译成DLL。 没有更多的pipe理部署脚本。
  4. 因为Linq可以支持查询实现IQueryable接口的任何东西,所以您将能够使用相同的语法来查询XML,对象和任何其他数据源,而无需学习新的语法

LINQ会膨胀过程caching

如果应用程序正在使用LINQ to SQL,并且查询涉及使用长度可变的string,则对于每个可能的string长度,SQL Server过程高速caching将变得臃肿。 例如,考虑在AdventureWorks2008数据库中针对Person.AddressTypes表创build的以下非常简单的查询:

 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过程caching中看到两个条目:一个绑定了NVARCHAR(7),另一个绑定了NVARCHAR(11)。 现在想象一下,如果有成千上万个不同的inputstring,所有string的长度都不相同 过程caching将变得不必要的完全相同的查询各种不同的计划。

更多信息: https : //connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=363290

我认为亲LINQ的观点似乎来自那些没有数据库开发历史的人(一般来说)。

特别是如果使用像VS DB Pro或Team Suite这样的产品,这里提出的许多参数不适用,例如:

更难维护和testing:VS提供完整的语法检查,样式检查,参照和约束检查等等。 它还提供完整的unit testingfunction和重构工具。

LINQ使得真正的unit testing变得不可能,因为(在我看来)它不能​​通过ACIDtesting。

在LINQ中debugging更容易:为什么? VS允许从托pipe代码和SP的定期debugging中全面介入。

编译成单个DLL而不是部署脚本:VS又一次来到了可以构build和部署完整数据库或进行数据安全增量更改的地方。

不需要学习LINQ的TSQL:不,你不需要学习LINQ – 哪里有好处?

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

呃,松耦合的应用程序是所有优秀程序员的最终目标,因为它们确实增加了灵活性。 能够孤立地改变事物是非常棒的,而且你的unit testing将确保它仍然返回适当的结果。

在你们所有人不高兴之前,我认为LINQ有它的地位,并有一个伟大的未来。 但是对于复杂的数据密集型应用程序,我不认为它已经可以取代存储过程了。 这是我在今年TechEd的MVP上所回应的一个观点(他们仍然是无名的)。

编辑:LINQ到SQL存储过程的一面是我仍然需要阅读更多 – 取决于我发现我可能会改变我的上面的谩骂;)

LINQ是新的,有它的地方。 LINQ不是为了取代存储过程而发明的。

在这里,我将专注于一些性能神话和CONS,只是“LINQ to SQL”,当然,我可能是完全错误的;-)

(1)人们说LINQ语句可以在SQL Server中“caching”,所以不会失去性能。 部分正确。 “LINQ to SQL”实际上是将LINQ语法转换为TSQL语句的运行时。 所以从性能的angular度来看,硬编码的ADO.NET SQL语句与LINQ没有任何区别。

(2)举一个例子,客户服务UI具有“账户转移”function。 这个函数本身可能会更新10个数据库表并返回一些消息。 使用LINQ,您必须构build一组语句并将其作为一个批处理发送到SQL Server。 这个翻译的LINQ-> TSQL批处理的性能几乎难以匹配存储过程。 原因? 因为可以使用内置的SQL事件探查器和执行计划工具来调整Stored程序中语句的最小单元,所以在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批次; 如果有一百万行,这是一个打击。 当然,有经验的用户不会用这种方式来做这个工作,但重点是,这样很容易陷入困境。

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

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

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

DBA没有自由地修改数据模型而不强迫你改变你的编译代码。 使用存储过程,您可以在某种程度上隐藏这些types的更改,因为从过程返回的参数列表和结果集代表其合同,并且只要该合同仍然得到满足,内部程序就可以改变。

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

恕我直言,RAD = LINQ,RUP =存储过程。 我曾在一家大型财富500强公司工作多年,包括pipe理层,坦率地说,我绝不会雇用RUP开发人员来开展RAD开发。 他们如此孤单,以至于他们在这个过程的其他层面上所做的事情知之甚less。 在一个孤立的环境中,让DBA通过非常具体的入口点来控制数据是有道理的,因为其他人坦率地不知道完成数据pipe理的最佳方法。

但是大型企业在发展领域动作缓慢,成本极高。 有时候你需要更快地节省时间和金钱,LINQ提供了更多的function。

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

我认为你需要与任何真正的特效。

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

B)我不相信对象build模总比关系build模好。

C)在SQL中testing和开发一个存储过程比任何Visual Studio环境下的编译过程快得多。 你只需编辑F5,然后select,然后你就可以参加比赛了。

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

E)LINQ到SQL仍然写不好的时候,蹩脚的代码。

老实说,我认为MS的最终目的是为了增加t-sql,这样它就可以按照linq的方式进行连接投影。 例如,t-sql应该知道你是否想要做order.lineitems.part。

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

还有可能的2.0回滚的问题。 相信我,这发生在我身上好几次了,所以我相信这发生在别人身上。

我也同意抽象是最好的。 除了事实之外,任何ORM的最初目的都是使RDBMS与OO概念相匹配。 但是,如果在LINQ之前一切正常,必须偏离OO概念,然后拧紧它们。 概念和现实并不总是很好的结合在一起。 IT部门的激进狂热分子没有空间。

我假设你的意思是Linq To Sql

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

另一方面,真正的交易破坏者将是一个问题,你是否觉得把你的业务逻辑放在你的数据库中是否合适,这是一个反对存储过程的论点。

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

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

希望它有帮助,我可能是错的。 :d

所有这些倾向于LINQ的答案主要是谈论EASE的发展,它或多或less与编码质量差或懒惰相关。 我只是这样。

Linq的一些优点,我在这里阅读,易于testing,易于debugging等,但这些都没有连接到最终输出或terminal用户。 这总是会给最终用户带来麻烦。 这是什么点加载内存中的许多东西,然后在使用LINQfilter?

TypeSafety再一次提醒说,“我们注意避免错误的types转换”,这也是我们试图通过使用linq来改善质量的问题。 即使在这种情况下,如果数据库中的任何变化,例如string列的大小,然后linq需要重新编译,不会没有types安全..我试过。

虽然我们发现在使用LINQ的时候是好的,甜蜜的,有趣的等等,但是它使得开发者懒惰的剪切力不足:),并且与存储过程相比,它被certificate是性能不好(可能最差)的1000倍。

不要懒惰 我正在努力。 🙂

存储过程与代码 (前面的讨论)

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

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

结果可以概括为:

LinqToSql适用于小型网站和原型。 这确实节省了原型的时间。

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

 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

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

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

Linq to Entities对于CRUD的快速开发非常有用。

当然,你可以只使用一个或另一个build立一个应用程序。 或者你可以把它混合起来。 这一切都归结于您的要求。 但SQL存储过程不会很快消失。