问题描述
ORM通常不涉及做诸如选择*之类的事情吗?
Doesn't an ORM usually involve doing something like a select *?
如果我有一个表MyThing,其中包含A,B,C,D等列,则通常会有一个对象MyThing,其属性为A,B,C,D.
If I have a table, MyThing, with column A, B, C, D, etc, then there typically would be an object, MyThing with properties A, B, C, D.
如果该对象没有被如下所示的select语句完全实例化,那只会是邪恶的,只会获取A,B,而不是C,D:
It would be evil if that object were incompletely instantiated by a select statement that looked like this, only fetching the A, B, not the C, D:
从MyThing中选择A,B/*不会得到C和D,因为我们不需要它们*/
select A, B from MyThing /* don't get C and D, because we don't need them */
但是总是这样做会很邪恶:
but it would also be evil to always do this:
选择A,B,C,D/*获取所有列,以便我们可以完全实例化MyThing对象*/
select A, B, C, D /* get all the columns so that we can completely instantiate the MyThing object */
ORM是否假设现在数据库访问是如此之快,而您不必担心它,因此您始终可以获取所有列?
Does ORM make an assumption that database access is so fast now you don't have to worry about it and so you can always fetch all the columns?
或者,您是否有不同的MyThing对象,可能恰好在select语句中的每个列组合中都有一个?
Or, do you have different MyThing objects, one for each combo of columns that might happen to be in a select statement?
在回答问题之前,请阅读Nicholas Piasecki和Bill Karwin的回答.我想我问的问题很差,因为很多人误解了它,但尼古拉斯100%理解了它.像他一样,我对其他答案也很感兴趣.
编辑#2:与该问题相关的链接:
EDIT #2: Links that relate to this question:
http://blogs.tedneward .com/2006/06/26/The + Vietnam + Of + Computer + Science.aspx ,尤其是部分对象问题和加载时间悖论"部分
http://blogs.tedneward.com/2006/06/26/The+Vietnam+Of+Computer+Science.aspx, especially the section "The Partial-Object Problem and the Load-Time Paradox"
http://groups.google.com/group /comp.object/browse_thread/thread/853fca22ded31c00/99f41d57f195f48b ?
http://www.martinfowler.com/bliki/AnemicDomainModel.html
http://database -programmer.blogspot.com/2008/06/why-i-do-not-use-orm.html
推荐答案
以我的有限经验,情况就如您所描述的那样-这是一个混乱的情况,通常的根据情况而定"的答案都适用.
In my limited experience, things are as you describe--it's a messy situation and the usual cop-out "it depends" answer applies.
一个很好的例子就是我工作的在线商店.它具有一个Brand
对象,并且在网站的主页上,该商店出售的所有品牌都列在左侧.要显示此品牌菜单,所有站点需要的是整数BrandId
和字符串BrandName
.但是Brand
对象包含其他属性的全部内容,最显着的是Description
属性,其中可以包含大量有关Brand
的文本.没有两种方法可以解决这个问题,即只是为了吐出一个无序列表中的名字而加载所有有关该品牌的额外信息,这是(1)可测量的,并且速度很慢,通常是因为文本字段很大;(2)出现这种情况时效率很低提高内存使用率,建立大型字符串,甚至在扔掉它们之前都不会看它们.
A good example would be the online store that I work for. It has a Brand
object, and on the main page of the Web site, all of the brands that the store sells are listed on the left side. To display this menu of brands, all the site needs is the integer BrandId
and the string BrandName
. But the Brand
object contains a whole boatload of other properties, most notably a Description
property that can contain a substantially large amount of text about the Brand
. No two ways about it, loading all of that extra information about the brand just to spit out its name in an unordered list is (1) measurably and significantly slow, usually because of the large text fields and (2) pretty inefficient when it comes to memory usage, building up large strings and not even looking at them before throwing them away.
许多ORM提供的一个选项是延迟加载属性.因此我们可以返回一个Brand
对象,但是直到我们尝试调用它的get
访问器时,该耗时且浪费内存的Description
字段才出现.届时,代理对象将拦截我们的调用,并及时从数据库中获取描述.有时这已经足够好了,但是已经让我非常恼火,以至于我个人不建议这样做:
One option provided by many ORMs is to lazy load a property. So we could have a Brand
object returned to us, but that time-consuming and memory-wasting Description
field is not until we try to invoke its get
accessor. At that point, the proxy object will intercept our call and suck down the description from the database just in time. This is sometimes good enough but has burned me enough times that I personally don't recommend it:
- 很容易忘记该属性是延迟加载的,仅通过编写一个foreach循环就引入了SELECT N + 1问题.谁知道当LINQ参与进来之后会发生什么.
- 如果由于传输混乱或网络中断而导致即时数据库调用失败怎么办?我几乎可以保证,任何执行
string desc = brand.Description
这样无害的代码都不会期望将DataAccessException
扔掉的简单调用.现在,您刚刚以令人讨厌且出乎意料的方式崩溃了. (是的,我已经看到我的应用程序因此而严重崩溃.学习了艰辛的方法!)
- It's easy to forget that the property is lazy-loaded, introducing a SELECT N+1 problem just by writing a foreach loop. Who knows what happens when LINQ gets involved.
- What if the just-in-time database call fails because the transport got flummoxed or the network went out? I can almost guarantee that any code that is doing something as innocuous as
string desc = brand.Description
was not expecting that simple call to toss aDataAccessException
. Now you've just crashed in a nasty and unexpected way. (Yes, I've watched my app go down hard because of just that. Learned the hard way!)
因此,我最终要做的是,在需要性能或易于出现数据库死锁的情况下,我创建了一个单独的接口,网站或任何其他程序都可以调用该接口来访问具有以下功能的特定数据块:仔细检查了他们的查询计划.该体系结构最终看起来像这样(原谅ASCII艺术):
So what I've ended up doing is that in scenarios that require performance or are prone to database deadlocks, I create a separate interface that the Web site or any other program can call to get access to specific chunks of data that have had their query plans carefully examined. The architecture ends up looking kind of like this (forgive the ASCII art):
Web Site: Controller Classes
|
|---------------------------------+
| |
App Server: IDocumentService IOrderService, IInventoryService, etc
(Arrays, DataSets) (Regular OO objects, like Brand)
| |
| |
| |
Data Layer: (Raw ADO.NET returning arrays, ("Full cream" ORM like NHibernate)
DataSets, simple classes)
我曾经以为这是作弊,颠覆了OO对象模型.但是从实际意义上讲,只要您使用此快捷方式来显示数据,我认为就可以了.更新/插入以及您仍然要通过完全水化的,充满ORM的域模型进行哪些操作,与显示数据的特定子集相比,这种情况发生的频率(在我的大多数情况下)要少得多.像NHibernate这样的ORM可以让您进行预测,但是到那时我还是看不到ORM的要点.无论如何,这可能都是一个存储过程,编写ADO.NET需要两秒钟.
I used to think that this was cheating, subverting the OO object model. But in a practical sense, as long as you do this shortcut for displaying data, I think it's all right. The updates/inserts and what have you still go through the fully-hydrated, ORM-filled domain model, and that's something that happens far less frequently (in most of my cases) than displaying particular subsets of the data. ORMs like NHibernate will let you do projections, but by that point I just don't see the point of the ORM. This will probably be a stored procedure anyway, writing the ADO.NET takes two seconds.
这只是我的两分钱.我期待阅读其他一些回复.
This is just my two cents. I look forward to reading some of the other responses.
这篇关于为什么ORM被认为是好的,但是“选择*"算不好吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!