我在StackOverflow(LINQ初学者指南)上看了一下"LINQ 初学者指南",但有一个后续问题:
我们即将推出一个新项目,几乎所有的数据库操作都将是相当简单的数据检索(项目的另一部分已经编写了数据).到目前为止,我们的大多数其他项目都使用存储过程来处理这些事情.但是,如果它更有意义,我想利用LINQ-to-SQL.
所以,问题是:对于简单的数据检索,哪种方法更好,LINQ-to-SQL或存储过程?任何具体的专业人士或骗子?
谢谢.
LINQ优于sprocs的一些优点:
类型安全:我想我们都明白这一点.
抽象:LINQ-to-Entities尤其如此.这种抽象还允许框架添加您可以轻松利用的其他改进. PLINQ是向LINQ添加多线程支持的示例.添加此支持的代码更改很少.完成简单调用sprocs的数据访问代码将变得更加困难.
调试支持:我可以使用任何.NET调试器来调试查询.使用sprocs,您无法轻松调试SQL,并且该体验主要与您的数据库供应商有关(MS SQL Server提供了查询分析器,但通常这还不够).
供应商不可知:LINQ适用于大量数据库,支持的数据库数量只会增加.由于语法或功能支持不同(如果数据库完全支持sprocs),Sprocs并不总是在数据库之间移植.
部署:其他人已经提到过这一点,但部署单个程序集比部署一组sprocs更容易.这也与#4联系在一起.
更简单:您不必学习T-SQL来进行数据访问,也不必学习调用sprocs所需的数据访问API(例如ADO.NET).这与#3和#4有关.
LINQ vs sprocs的一些缺点:
网络流量:当LINQ发送整个查询时,sprocs只需要通过线路序列化sproc-name和参数数据.如果查询非常复杂,这可能会非常糟糕.但是,LINQ的抽象允许微软随着时间的推移改进这一点.
灵活性较差:Sprocs可以充分利用数据库的功能集.LINQ在它的支持中往往更通用.这在任何类型的语言抽象中都很常见(例如C#与汇编程序).
重新编译:如果需要更改数据访问方式,则需要重新编译,版本和重新部署程序集.Sprocs 有时可以允许DBA调整数据访问例程,而无需重新部署任何内容.
安全性和可管理性也是人们争论的问题.
安全性:例如,您可以通过直接限制对表的访问来保护敏感数据,并将ACL放在sprocs上.但是,使用LINQ,您仍然可以限制对表的直接访问,而是将ACL放在可更新的表视图上以实现类似的结束(假设您的数据库支持可更新视图).
可管理性:使用视图还可以使您的应用程序不受模式更改(如表规范化)的影响.您可以更新视图,而无需更改数据访问代码.
我曾经是一个大家伙,但我开始倾向于LINQ作为一般的更好的选择.如果有一些区域的sprocs显然更好,那么我可能仍然会编写一个sproc但是使用LINQ访问它.:)
由于DBA多年来一直在努力的所有原因,我通常支持将所有内容都放在存储过程中.对于Linq,确实与简单的CRUD查询没有性能差异.
但在做出这个决定时要记住一些事项:使用任何ORM将您紧密地联系到您的数据模型.DBA无法自由更改数据模型,而无需强制更改已编译的代码.使用存储过程,您可以在一定程度上隐藏这些类型的更改,因为从过程返回的参数列表和结果集表示其合同,并且只要合同仍然满足,就可以更改内部条件. .
而且,如果Linq用于更复杂的查询,调整数据库将变得更加困难.当存储过程运行缓慢时,DBA可以完全专注于代码,并且有很多选项,这样只要合同在他/她完成时仍然满足.
我已经看到很多很多情况,通过更改存储过程中的模式和代码来解决应用程序中的严重问题,而不会对已部署的已编译代码进行任何更改.
也许一个混合方法对Linq来说会很好吗?当然,Linq可用于调用存储过程.
Linq到Sql.
Sql server将缓存查询计划,因此sprocs没有性能提升.
另一方面,您的linq语句将在逻辑上与您的应用程序一起进行测试.Sprocs总是有点分开,难以维护和测试.
如果我现在正在从头开始研究一个新的应用程序,我会使用Linq,没有sprocs.
对于基本数据检索,我会毫不犹豫地去找Linq.
自从搬到Linq后,我发现了以下优点:
调试我的DAL从未如此简单.
当架构更改无价时,编译时间安全性.
部署更容易,因为所有内容都编译成DLL.不再管理部署脚本.
因为Linq可以支持查询实现IQueryable接口的任何内容,所以您将能够使用相同的语法来查询XML,对象和任何其他数据源,而无需学习新的语法
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?反馈ID = 363290
我认为专业LINQ论证似乎来自那些没有数据库开发历史的人(一般而言).
特别是如果使用VS DB Pro或Team Suite等产品,此处提出的许多参数都不适用,例如:
更难以维护和测试:VS提供完整的语法检查,样式检查,参考和约束检查等.它还提供完整的单元测试功能和重构工具.
LINQ使真正的单元测试变得不可能,因为(在我看来)它没有通过ACID测试.
LINQ中的调试更容易:为什么?VS允许从托管代码完全步入并定期调试SP.
编译成单个DLL而不是部署脚本:再次,VS可以构建和部署完整数据库或进行数据安全的增量更改.
不必用LINQ学习TSQL:不,你不需要,但你必须学习LINQ - 哪里有好处?
我真的不认为这是一种好处.能够孤立地改变某些东西在理论上听起来不错,但仅仅因为改变履行合同并不意味着它正在返回正确的结果.为了能够确定正确的结果是什么,您需要上下文,并从调用代码中获取该上下文.
嗯,松散耦合的应用程序是所有优秀程序员的最终目标,因为他们确实提高了灵活性.能够孤立地改变事物是很棒的,而且你的单元测试将确保它仍然能够返回适当的结果.
在你们都感到不安之前,我认为LINQ有它的位置并且有一个美好的未来.但对于复杂的数据密集型应用程序,我认为它不准备取代存储过程.这是我今年在TechEd的一个MVP回应的观点(他们将保持无名).
编辑:LINQ to SQL存储过程方面的东西是我仍然需要阅读更多 - 取决于我发现我可能会改变我的上述dia骂;)
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批次; 如果有数百万行,这是一个打击.当然,有经验的用户不会用这种方式来完成这项工作,但重点是,这样很容易.
最好的代码是没有代码,并且对于存储过程,您必须在数据库中编写至少一些代码并在应用程序中编写代码来调用它,而使用LINQ to SQL或LINQ to Entities,您不必编写任何其他代码除了实例化上下文对象之外,代码超出任何其他LINQ查询.
LINQ绝对在特定于应用程序的数据库和小型企业中占有一席之地.
但在大型企业中,中央数据库充当许多应用程序的通用数据中心,我们需要抽象.我们需要集中管理安全性并显示访问历史记录.我们需要能够进行影响分析:如果我对数据模型进行一些小改动以满足新的业务需求,需要更改哪些查询以及需要重新测试哪些应用程序?观点和存储过程给了我这个.如果LINQ可以做到这一切,并使我们的程序员更高效,我会欢迎它 - 有没有人有在这种环境中使用它的经验?
DBA无法自由更改数据模型,而无需强制更改已编译的代码.使用存储过程,您可以在一定程度上隐藏这些类型的更改,因为从过程返回的参数列表和结果集表示其合同,并且只要合同仍然满足,就可以更改内部条件. .
我真的不认为这是一种好处.能够孤立地改变某些东西在理论上听起来不错,但仅仅因为改变履行合同并不意味着它正在返回正确的结果.为了能够确定正确的结果是什么,您需要上下文,并从调用代码中获取该上下文.
恕我直言,RAD = LINQ,RUP =存储过程.我在一家大型财富500强公司工作了很多年,包括管理层在内的许多层面,坦率地说,我绝不会聘请RUP开发人员来开发RAD.它们是如此孤立,以至于他们对在该过程的其他层面上做什么的知识非常有限.对于孤立的环境,让DBA通过非常具体的入口点控制数据是有意义的,因为其他人坦言不知道完成数据管理的最佳方法.
但大企业移动痛苦地在发展领域缓慢,这是极其昂贵的.有些时候你需要更快地移动以节省时间和金钱,LINQ提供了更多的功能.
有时我认为DBA对LINQ有偏见,因为他们认为这会威胁到他们的工作安全.但这就是野兽的本质,女士们,先生们.
我认为你需要使用procs来获得任何真实的东西.
A)在linq中编写所有逻辑意味着您的数据库不太有用,因为只有您的应用程序可以使用它.
B)我不相信对象建模比关系建模更好.
C)在SQL中测试和开发存储过程比任何Visual Studio环境中的编译编辑周期快得多.你只需编辑,F5并点击选择即可参加比赛.
D)管理和部署存储过程比组件更容易..你只需将文件放在服务器上,然后按F5 ...
E)Linq to sql仍然会在你不期望的时候编写糟糕的代码.
老实说,我认为MS的最终目的是增加t-sql,以便它可以像linq那样隐含地进行连接投影.例如,t-sql应该知道你是否想要订购order.lineitems.part.
LINQ不禁止使用存储过程.我使用了LINQ-SQL和LINQ-storedproc的混合模式.就个人而言,我很高兴我不必编写存储过程.... pwet-tu.