Linq到SQL没有错过点? 不是ORM映射器(SubSonic等)次优解决scheme?
我希望社区对Linq to Sql和其他ORM映射器有一些想法。
我喜欢Linq to Sql和在本地开发语言中expression数据访问逻辑(或一般CRUD操作)的想法,而不必处理C#和SQL之间的“阻抗不匹配”。 例如,要为业务层返回一个与ObjectDataSource兼容的Event实例列表,我们使用:
return db.Events.Select(c => new EventData() { EventID = c.EventID, Title = c.Title })
如果我要使用旧的SQL-to-C#构造来实现这一点,那么必须创build一个Command类,添加EventID参数(使用string来描述“@EventID”参数),将SQL查询string添加到Command类,执行该命令,然后使用(cast-type)nwReader [“FieldName”]来提取每个返回的字段值,并将其分配给新创build的EventData类(yuck)实例的成员。
所以, 这就是为什么像Linq / SubSonic /等人。 并且我同意。
但是,从更大的angular度来看,我发现了一些错误的东西。 我的感觉是,微软也看到了一些错误,这就是为什么他们要杀Linq到SQL,并试图将人员转移到Linq的实体。 只是,我认为微软在一个糟糕的赌注上翻了一番。
那么,什么是错的?
问题是有架构的宇航员 ,特别是在微软,看着Linq to Sql,意识到这不是一个真正的数据pipe理工具:在C#中仍然有许多事情你不能轻松做到,他们的目标是修复它。 Linq to Entities背后的雄心,Linq 革命性的博客文章甚至LinqPad的挑战 ,都体现了这一点 。
而问题是,它假定SQL是问题。 也就是说,为了减less轻微的不适感(SQL和C#之间的阻抗不匹配),当一个创可贴(Linq to SQL或类似的)可以很好地完成时,微软已经提出了相当于一个太空套装(完全隔离)。
据我所知,开发人员非常聪明,掌握关系模型,然后在开发工作中智能地应用它。 事实上,我会更进一步说,Linq到SQL,SubSonic等已经太复杂了:学习曲线和掌握SQL本身并没有太大的区别。 由于在可预见的将来,开发人员必须掌握SQL和关系模型,现在我们正面临着学习两种查询/ CRUD语言。 更糟糕的是,Linq通常很难testing(你没有查询窗口),从我们正在做的实际工作中移除了一层(它生成SQL),并且对SQL结构的支持(最好)非常笨拙date处理(如DateDiff),“有”,甚至“分组依据”。
有什么select? 就个人而言,我不需要像Linq to Entities这样的数据访问模式。 我宁愿在Visual Studio中popup一个窗口,input并validation我的SQL,然后按下button生成或补充一个C#类来封装调用。 既然你已经知道SQL,你不喜欢只input这样的东西:
Select EventID, Title From Events Where Location=@Location
并最终得到一个EventData类,A)包含EventID和Title字段作为属性,B)有一个工厂方法,它将一个'Location'string作为参数,并生成一个List <EventData>? 你必须仔细考虑对象模型(上面的例子显然不涉及这个),但是在消除阻抗不匹配的情况下仍然使用SQL的基本方法吸引了我很多。
问题是:我错了吗? 微软是否应该重写SQL基础架构,以便不必再学习SQL /关系数据pipe理? 他们可以用这种方式重写SQL基础结构吗? 或者你认为在SQL之上的一个非常薄的层,以消除设置参数和访问数据字段的痛苦是足够的?
更新我想推广两个链接到顶端,因为我认为他们捕捉了我所追求的重要方面。 首先,CodeMonkey指出了一篇题为“越南计算机科学”的文章。 开始需要一段时间,但是是一个非常有趣的阅读。 其次,AnSGri指出乔尔·斯波尔斯基(Joel Spolsky)的其中一个更为突出的部分: “泄漏抽象法则”(The Law of Leaky Abstractions) 。 这是不是在主题上,但它是密切的,是一个伟大的阅读。
更新2:我给了ocdecio“答案”,虽然这里有很多很好的答案,而“正确的”答案的select纯粹是主观的。 在这种情况下,他的回答与我认为是目前技术状况下的最佳做法是一致的。 然而,这是一个我完全期望发展的领域,所以事情可能会改变。 我想感谢每个人的贡献,我赞成每个人,我认为给了一个深思熟虑的答案。
至less6年来,我一直在使用自己的基于一个非常简单的概念的ORM:投影。 每个表都投影到一个类中,SQL根据类的定义随时生成。 它仍然需要我了解SQL,但它需要90%简单的CRUD,而且我从来不需要pipe理连接等,而且它适用于主要数据库供应商。
我很高兴我有什么,没有find任何值得放弃的东西。
让我先说这个,说我是一个染色的数据库人。
作为一个总的过度概括 :开发人员不知道SQL。 开发人员并不真正想知道SQL。 他们可以写它,他们可以devise表,但它使他们感到恶心。 当必要的查询不仅仅是一个简单的连接时,他们往往会做一些愚蠢的事情。 不是因为开发商很愚蠢 – 因为他们不能被打扰。 他们喜欢生活在一个只能处理一个概念空间的世界, 从对象移动到表格并返回是上下文切换他们不喜欢支付的价格。
这并不意味着他们是坏的或错误的; 这意味着有改进的机会。 如果您的客户(在这种情况下,使用您的框架的开发人员)不喜欢SQL和表 – 给他们一个抽象层,让他们离开而不处理底层的混乱。
垃圾收集/自动化内存pipe理是一个重要的逻辑。 是的,开发人员可以处理它; 是的,他们可以编写没有它的代码更好的优化; 但不必处理它使他们更快乐,更有成效。
我认为ORM的普及已经由开发人员开发数据层并在应用程序之后重复编写相同的CRUD代码而产生。 ORM只是另一种工具/技术,它可以让开发人员花费更less的时间反复编写相同的SQL语句,而不是专注于应用程序的逻辑(希望)。
恕我直言,OR / M不仅是“抽象SQL”或隐藏SQL,或启用多数据库支持。
它使您能够更专注于您的问题领域,因为您必须花更less的时间编写无聊的CRUD SQL查询。 另一方面,如果你正在使用一个好的OR / M,这个OR / M应该使你能够编写SQL查询,如果这似乎是必要的。
如果正确使用,OR / M可能是一个强大的工具; 它可以照顾延迟加载,多态查询/关联…
不要误会我的意思; 普通的SQL没有什么问题,但是如果你不得不把自己的(精心devise和规范化的)关系模型转换成一个expression式的面向对象/域模型,那么我认为你花了很多时间去做pipe道工。
使用OR / M也并不意味着你作为一个开发人员不应该有SQL的知识。 相反是真实的imho。
了解SQL并知道如何编写高效的SQL查询,将使-imho-能够正确使用OR / M。
我也必须承认,我正在用NHibernate来写这个。 这是我使用atm的OR / M,我还没有使用Linq到SQL或Linq到实体(还)。
Linq的devise和linq to entities框架当然是作为一个orm工具使用的,但是最大的想法是它将被用作查询任何数据源的通用API,而不仅仅是RDBMS。
我记得读过linq,虽然显然是用SQLdevise的,但它是为任何数据存储提供查询语言的。 您可以编写SQL的linq查询,但是您理论上也可以编写针对ldap,文件系统,交换,Web服务和无限的linq查询。 这些程序不能使用SQL。
几乎每个数据存储都需要学习不同的API。 Linq给每个人一个共同的目标来创build一个数据访问API。
这个愿景是否有效还有待观察,但这就是这个想法。 我认为,因为我们希望系统越来越多地相互操作,所以我们可能会发现l2e的一些非常好的用途。
如果我能find它们,我会添加一些参考。
http://laribee.com/blog/2007/03/17/linq-to-entities-vs-nhibernate/
你应该停止担心和学习爱ORM。 像这些抽象将帮助我们集中我们的技能,并在该领域取得进展。
还有足够的空间来利用你已经获得的function技能,并将其应用于应用层。 这实际上是LINQ to SQL比其他ORM更强大的优势之一。
我只能同意其他许多意见。 你节省的时间,你可以专注于改善你的领域模型,并做出更好的应用程序。 而且,一旦您确定了瓶颈,请使用创build优化的SQL。
ORM带有许多非常好的特性,可能不是很明显。 有助于避免重复加载项目的身份映射,延迟加载可帮助您用较less的pipe道来expression域,而工作单元可帮助您跟踪更改并优化数据库写入。
我同意100%。 这很大程度上是程序编码技能和SQL编码技能非常不同的结果, 而这个事实并没有得到广泛的承认。 所以,直到实现命中为止,程序员才能find让他们的技能从一个领域转移到另一个领域的方法。
它不起作用。
你只需要学习如何进行相位转换:学习如何根据你正在寻址的领域来对代码进行不同的思考。
有没有人注意到,从SQL到LINQ映射的查询会变得多复杂和冗长? 就像所有的在线例子一样?
正如德米特里指出的那样 ,开发人员不知道SQL。 更确切地说,大多数人都知道 SQL,但不了解它,肯定不喜欢,所以他们倾向于寻找神奇的子弹,创造像Linq这样的东西的需求,使他们的幻想(嗯,抽象)不会使用与他们喜爱的课程不同的东西。
这是非常糟糕的,因为泄漏抽象的规律总是成立的。
有些ORM解决scheme确实很好(如JPA / Hibernate),不是因为使用它们,你不必担心SQL。 实际上,要有效地使用JPA,你需要对数据库有非常深入的了解,特别是查询能力。 好的一点是,他们让机器做无聊的工作 ,从头开始自动生成整个数据库。
Linq to SQL,我认为,并不能解决真正的问题。 这是一种其他的演示,没有什么更多。 这可能是好的,虽然它已经过分复杂的语言。 另一方面,Linq to Objects是一个非常有趣的概念,因为它是一种查询集合的方法。
历史的angular度。
当Codd et。 人。 最初是在研究关系数据库的理论和实现,一个完全独立的问题是“我们如何查询这些东西”? 提出了许多策略和语法,各有优缺点。 其中一个候选人是SQL(显然是最早的forms)。另一个是QBE(Query By Example)。 另一个叫“奎尔”,我相信。 还有其他几个。 SQL当然没有成为主导,因为它被认为优于所有其他的。 然而,其他人几乎完全消失了,我们大家都贫穷了(因为他们可以同时使用相同的数据)。
如果微软有一个好的故事,那就是他们正在复兴其中一种语言,或者发明了一个有价值的东西,那么我认为我们会被build议倾听。 但到目前为止,我所看到的还是另一个“一个统治者”。
SQL背后有很多深思熟虑的东西,还有很多久经考验的耐久性。 微软有一定的历史相信,他们公认的高级发展组织可以超出我们其他人,包括我们集体的机构记忆。 这似乎并不经常这样工作。 只要我们关系到关系数据存储,我们就应该思考超集抽象范式,这些范式使我们远离裸机,并承诺性能相同或更好。
作为一个ORM项目的作者,我不得不承认,我对这个问题的回应往往有点偏颇。 在阅读问题之前,我已经对自己的答案有了一些自己的想法,所以我已经有所了解了。
我会说我开发ORM的原因不是因为SQL和命令式编程之间的“阻抗不匹配”,而仅仅是为了成为数据库平台不可知的目的。 前一个编写更多代码来pipe理持久性的问题是一个很小的障碍,如果你只与一个数据库供应商合作,这个问题很容易解决。 成为数据库平台不可知论者是一个更具挑战性的问题,假设像我一样计划向其他人出售软件(而不仅仅是在内部使用),imo对你的业务的盈利能力有更大的影响。
当我几年前开始使用我的ORM工具时,这个概念在我的首选语言中是不切实际的,我所交谈的大多数人都不明白我为什么要这样做,社区中一些备受尊敬的声音和写作文章一样多在贸易杂志上说,我已经做了不仅不可能,而且也是不可取的。 一些相同的原因被给出 – 这太复杂了,这是限制性的,并增加了开销。 现在,同一个社区至less有三个stream行的数据库抽象工具(尽pipe对ORM这个术语的定义有一些争论)。 我之所以提到这个,是因为当我开始研究这些工具时,原来的反对意见比现在要重要得多。 在这段时间内,硬件和软件的基础技术已经发生了变化,从长远来看使这些工具变得更加实用。 我的倾向是尝试从软件的长远angular度出发,研究可能不太实用的解决scheme,但很快就会实现。 所以鉴于我不会把LINQ to Entities算作一个很好的解决scheme。
我也倾向于select更多的select,而不是更less的select。 所以,虽然我可能支持开发LINQ to Entities的想法,但我不太容易支持将LINQ to SQL杀死,因为LINQ to Entities已经可用。 对象是做什么对象做的伟大的,这是毫无疑问的…在我的(也是有偏见的)意见,一个问题发生在人们看到任何给定的工具或软件范例作为一个“魔术子弹”,并希望坚持一切必须是这样的。 众所周知,关系数据库在处理某些其他任务方面非常擅长,报表就是一个很好的例子。 所以在我看来,这是一种坚持一切都必须是实体的方式,因为那样你就会迫使自己使用效率低下的工具。 所以特别是在报告方面,摆脱LINQ to SQL,至less在表面上只使用LINQ to Entities听起来像是抽象反转反模式。
所以我想我的答案是这样的概要:如果你的问题是钉子,使用锤子 – 如果你的问题是螺丝钉使用螺丝刀。
德米特里的声明,开发人员不喜欢SQL可能有很多的事实,但解决scheme不仅是ORM。 解决scheme是作为开发团队的一部分聘请开发DBA。 在我的公司,我的.net开发团队拥有一名优秀的Oracle DBA,他绝对没有生产dba的工作。 他在我们团队中的angular色是数据build模,物理数据库devise,创build存储过程,数据分析等。他是我们数据库方面如此干净和performance的原因。 我们所有的DB访问都是通过存储的特效。
什么是开发DBA? http://www.simple-talk.com/sql/database-administration/what-use-is-a-development-dba/
我认为这些背后的逻辑是在框架层构build和运行SQL语句的开销与系统其他部分的开销(例如,HTTP请求往返时间要长几个数量级)相比是微不足道的。
优点 – 快速的开发,适合于语言的查询而不是逃避string等,通常大于缺点。 如果性能是一个问题,那么你可以稍后进行优化。
我不认为“不需要知道SQL”是一个因素。 任何像样的开发人员都需要在开发过程中了解SQL。 数据库抽象层的思想是消除为数据库查询生成样板代码的工作。
事实上,在我们的Java系统中,我创build了一个代码生成器实用程序,它使用带注释的类并生成一个完整的CRUD API,并处理所有那些随着时间推移而挑选的古怪事物。 通过编写一个DAO,创build你的模型和注释比创build模型更容易。 扩展这样一个工具,最终得到LINQ或Hibernate或其他ORM DB解决scheme。
我同时做数据库和分布式应用程序编程(networking和编译),觉得花时间开发基于存储过程的数据访问层是花费时间的。 就个人而言,我更喜欢在开发过程的早期进行数据build模和识别所需的过程,似乎有助于发现devise/接口逻辑/结构问题。
我不是内联数据库编程的忠实粉丝(不pipesql代码是手工还是机器生成的)。 我相信数据库是一个应用程序的基础,花时间手工编写存储过程是值得的。
也就是说,我对OODBMS概念很感兴趣,并希望有一天我能够在生产环境中开展工作。
如果您希望数据库在扩展时执行,则必须根据数据库关系模型最佳实践进行devise和规范化。
如果让对象模型和ORM指定你的数据模型,那么你最终会得到一个不规范的数据模型,或者包含对象模型中的工件。
1表= 1类是一个坏主意。
首先,你永远不会有代表多对多或多对一链接表的类。 这些对应于对象模型中的子集合 – 链接本身不是对象。
如果您将数据库视为表来简单地将对象保存在行中(一种常见方法),并让应用程序直接访问表,那么您将放弃定义数据库服务的接口层的所有好处,数据库可用来保护它的外围。
ORM有它们自己的位置,但是如果使用它们来简单地保持对象模型中devise的对象,那么您的数据库将不会是关系数据库,并且将不能用作ETL,报告,重构等
还有一个问题是关于ORM的问题 。 检查一下更多的讨论是否阻抗不匹配是一样大的交易。
我认为他们需要的真正的解决scheme更像SQL文字。 VB.Net 9.0支持XML Literals ,它允许您在代码中正确编写XML,并确保validation它并符合DTD。 一个类似的好function是SQL文字,它允许你在你的.Net代码中编写内联的SQL代码,并由IDE进行validation。 需要有某种插件体系结构来validation数据库的信息,但这可以很容易地写入stream行的数据库引擎。 这将提供我认为是真正的解决scheme,解决他们正在试图解决的问题,而不诉诸次优解决scheme。
Codemonkey提供了一个很好的观点:存储过程提供了一个抽象级别来满足更复杂的ORM模型的一些承诺。 乍一看这并不直观,但我可以从我自己的代码中想到一个例子。 我有一个“签入”的存档,涉及近十几个表(这个ID是谁的?他们是否有会员资格?是否有任何消息?他们是否得到这个签入点?等等)。
Modeling this in C# – no matter how sophisticated the data model – would never be a good idea as it would necessitate many trips "over the wire" to check on data and update various tables. While it is true that you can handle sprocs in Linq or other ORMS, all I need is a wrapper class that allows me to call the sproc with standard C# parameters. In fact, this was such a pressing need for me that I wrote a code generator in T-SQL to create such wrappers.
I don't like any of the current solutions – but i prefer more choices over less choices 😉
i used an OODBMS in a project long ago that was the closest to getting it right (unfortunatley the product had some heinous bugs and terrible tech support) – object persistence was largely invisible , handled behind the scenes (via preprocessor code-generator) and controlled by very simple Update, Delete, and Find methods and simple containers.
I'd love to see this (and perhaps some object-entity model does this well already) again, with OCL (Object Constraint Language) as the native multi-object query language
I have to agree that the outburst of ORM tools largely stems from the annoyance of writing SQL, dealing with whatever DB driver you have to use, internally abstracting between DBs (Oracle vs SQL Server, vs whatever for code reusability), and transforming data types.
Ideal solution? definately not! However, I think this is an iteration in the process of better merging the application with the data store. After all, in most cases, having a DB without an accessing application written in whatever language is practically useless. (would you really ever just install oracle, and expect all employees to work in SQLPlus directly?)
As such, I think the data store and the application are just moving together in a way that the application developer can more easilly interact with the data store.
For .NET in particular, what I'd much rather see instead of Linq is a built in way to map a class definition to an underlying data source to an underlying data store, and have all the plumbing just work.
In other words I could just say "Employee.Name = 'rally25rs';" and the object's property would change, and underneath that it would persist to the data store itself. Just ditch SQL completely instead of going 1/2 way like Linq to SQL does now.
Of course, a solution like that brings up issues with performance, transaction handling, etc.
Maybe the entire concept of programming language and relational database need to be rethought and realigned? At their core, they are completely separate and disjointed entities. Maybe its time to just ditch the "relational sql aware database" and build the next thing, whee executing a line of code would directly operate on the database.
there´s no problem with linq, but with those who use it and ignore what happens "behind the scenes"
I still prefer to get my hands dirty with SQL. At least i´ll know exatcly whats happening.
Ted Neward wrote a great essay on his take on this subject – that ORM's are the "Vietnam" of computer science…
http://blogs.tedneward.com/2006/06/26/The+Vietnam+Of+Computer+Science.aspx
Most people have missed an essential point: in most cases, you are significantly more productive when querying in LINQ than in SQL. I've written an article on why this is so.
When I set the LINQPad Challenge, I wasn't joking: I do nearly all of my ad-hoc querying in LINQ because most queries can be written more quickly and reliably in LINQ than in SQL. I've also designed and worked on large business applications using LINQ to SQL and seen a major gains in productivity. This is not "architecture astronaut" stuff – LINQ to SQL is a productive and practical technology that drives this very site .
The biggest hindrance with LINQ is failing to properly learn it. I've seen so many LINQ queries that are horrible transliterations of SQL queries to back this up. If you write LINQ queries using only your knowledge of SQL, the end result can only be the same – or worse – than SQL.
I just discovered this question. I guess it's pretty much played out by now, but I'm going to throw in my two cents anyway…
I only want to write code for the things that aren't obvious.
CRUD code is obvious. I don't want to write it. Therefore, ORMs are a good idea.
This doesn't mean that ORMs don't have problems, but the problems are with execution, not intent. As ORMs mature, the problems will diminish, and the productivity gains already available for simple scenarios will eventually extend to complex scenarios as well.
LINQ is also a good idea. Others have mentioned a number of the advantages, but all I have to do is think about the first time I tried to do a pivot in LINQ where I didn't know the number of columns in advance. Or the first time I realized I didn't have to create a new DataView
every time I wanted to sort or filter something. LINQ empowers me to do everything I want to do with data in C#, rather than having to figure out how divide up the work between SQL and C#.
So, yes, ORMs, LINQ, and other emerging technologies are suboptimal solutions, but they don't miss the point, and they won't be suboptimal forever.
I wanted to write this as a reply to @SquareCog reply here , but it told me I had -1836 characters left. SO noob here so apologies if I've done this wrong.
In the 18th century gentleman of leisure used to study science. At that time science in its entirety was not such a large subject that a reasonably intelligent person couldn't understand it all. By which I mean a single learned fellow could understand the entirety of scientific thinking of the time.
As time has gone by hundreds of new fields of science have been discovered and each one researched to the point where these days very few people can even understand the entirety of a single complete field of science.
So it is with programming.
These days the programming language field is large enough and growing fast enough that it is as much as can be reasonably be expected of a developer to know the entirety of his own specialised languages(s). For a skilled coder to also be expected to understand the entirety of the database field too, including database design, the nuances of native SQL and how it operates on different databases and the administration of those databases too, is possibly asking a bit much.
I think some of the responders here are glossing over some of the complexities of developing a large performant enterprise level database, knowing a 'handful of SQL statements' most certainly does not cut it. Which is why most large software houses have dedicated teams of database developers. As Stroustrup says, 'Divide and conquer' is the only way to effectively deal with the complexity inherent in developing and managing large software projects.
Developers don't dislike working with SQL because they are lazy or because it makes them feel 'icky'. They dislike working with SQL because they are smart. They know better than anyone that only someone who specialises in SQL will deliver the highest quality database functionality and that for them to be put into the position of being 'jack of all trades' developers is a suboptimal development strategy.