60

EDIT: Original Title: Question about the benefit of using an ORM.

I want to use an ORM for learning purposes and am try nhibernate. I am using the tutorial and then I have a real project. I can go the "old way" or use an ORM. I'm not sure I totally understand the benefit. On the one hand I can create my abstractions in code such that I can change my databases and be database independent. On the other it seems that if I actually change the database columns I have to change all my code.

Why wouldn't I have my application without the ORM, change my database and change my code, instead of changing my database, orm, and code? Is it that they database structure doesn't change that much?

I believe there are real benefits because ORMs are used by so many. I'm just not sure I get it yet.

Thank you.

EDIT: In the tutorial they have many files that are used to make the ORM work

http://www.hibernate.org/362.html

In the event of an application change, it seems like a lot of extra work just to say that I have "proper" abstraction layers. Because I'm new at it it doesn't look that easy to maintain and again seems like extra work, not less.

EDIT: This is an old question I keep coming back to. What I want to see if an example of properly designing an application without an ORM and without using embedded SQL and without using .NET LINQ-to-SQL, no offense. I'm in the Java world at the moment, and I'm lost on how to proceed. It is a web application. No Spring, no other worldly frameworks. JSP, JSTL, EL, HTML, JavaScript, CSS, Java, Tomcat. Hope I didn't leave anything out. And yes, I know it is an old question. It is still relevant.

johnny
  • 19,272
  • 52
  • 157
  • 259

10 Answers10

123

Why, oh why, is the industry so wedded to this disaster of a concept? None of the previous answers adequately addresses @johnny's concerns. They are all half-baked hand-waving justifications that steer well clear of the concrete issues facing database programmers.

@TheTXI's answer is typical of the responses I get when asking the same question: separation of layers. What is that supposed to mean? Why do I want to separate my layers? Or, more to the point, how does it benefit me to create an additional layer that is different to the relational layer and yet is supposed to be a canonical mapping from that layer?

Furthermore, (@johhny's as-yet unanswered point) how does this protect us from change? If the database changes, the ORM layer will almost certainly have to follow suit. In fact, the default practice of not modeling join tables at the object level makes this even worse, because when the table inevitably grows some extra columns, you not only add some extra fields to the object model, but you also change its topology and force a bunch of code rewrite! This is a disaster for change management and is a classic example of how a misguided view of relations (thinking they represent objects) courts disaster. This simply wouldn't have occurred if you just mapped the relational database directly into congruent notions in the programming language (think LINQ-to-SQL, and not LINQ-to-EF).

The biggest unanswered question in this space — the elephant in the room — is: what problem is ORM supposed be solving? And don't say "object-relational impedance mismatch". That's just another hand-waving fob-off. Explain why there is an impedance mismatch, and why it should be the database that comes to the language rather than the language going to the database. My explanation is that most programming languages suck at expressing and working with relational data, but that this is a historical reality that is beginning to slip away (LINQ-to-SQL was the first baby-step in that direction), not a fundamental principle on which to base sound architecture.

There's a reason that ORMs have become so complex, with lazy-loading, caching, a bewildering array of persistence and ownership semantics, etc. And there's a reason that for all this extra pounding away at the keyboard, they still fail to efficiently solve basic problems like, "Which pairs of members share more than one group?" The relational model was conceived at a time when network and heirarchical models were buckling at the knees under the weight of such problems; it was a breath of fresh air. Now we all seem to yearn to go back to our old sandpit full of cat-pee, and we think we've invented something new (as long as we hold our noses).

(I fully expect to be liberally down-voted on this answer. But please leave a comment when you do. I don't mind being told I'm wrong, as long as I know why.)

EDIT: Thank you @Chris for taking the time to comment. It gives me some concrete points to address... (Note that while I frequently address @Chris below, I am not trying to take him to task specifically; his responses are typical of the kinds of comments I hear all the time when discussing the subject. So I hope he doesn't take my criticisms as a personal affront; they are not intended that way, and I do genuinely appreciate the time he took to respond.)

First off, let me clear up some misconceptions evident in @Chris's comments and answer.

  1. I do not advocate raw SQL in code, for all the obvious reasons, and some not so obvious ones (e.g., SQL is neither an algebra nor a calculus, which makes functional decomposition virtually impossible).
  2. I do not advocate monolithic application design. Layers are, in general, a good thing.
  3. I do not advocate polluting object models with lots of line-noise such as special fields, methods, and attributes. Frankly, however, this is a strawman, since domain/object models only exist in the ORM universe. Now, I know LINQ-to-SQL has all these classes with lots of noisy bits in them, but they are just behind-the-scenes plumbing; you don't edit that code, and you generally shouldn't even look at it.

Now some objections to the objections:

  1. The assertion that applications can be built independently of the database is unfounded. By and large, ORMs are just a canonical mapping onto the data layer (Tables Foo and Bar become classes Foo and Bar, and table FooBar becomes some kind of torrid affair between classes Foo and Bar). There isn't much wiggle room in this mapping, and so any change to the data model will almost certainly require a corresponding change to the object model. This is a good thing in my view, since an object that radically diverged from the corresponding database model would be nothing more than an additional maintenance headache for all concerned.
  2. Once the illusion that ORMs engender data-model-independence is discarded, all protestations about the evils of direct coupling to the data model become moot. But I'd like to pursue this a little further than to simply dismiss it. Coupling is an essential feature of system design. At some point, decisions and assumptions have to be made. You can't program everything using a single "Things" table. You have to decide that your domain contains certain specific concepts and then create schemas and code that respect those concepts, treat them as first-class citizens, hard-code them. The idea that applications ought to be independent of the database is misguided. The database is (or ought to be) the purest representation of a business's knowledge (I know that this isn't always the case, and I will address this later). Coupling to this representation ought to provide the strongest guarantee of resilience, since such a data model will only change when the business itself undergoes some intrinsic change. In short, coupling to a well-designed database schema is a very good thing.
  3. Layering is not an end in its own right. It is good because it achieves some specified goal. The preceding points show that layering between the database and the app in the way ORM does is neither effective nor necessary to achieve the real goal of resilience to change. This is achieved through good database design.
  4. @Chris asserts that letting the database dictate things stymies OO design. This is true enough, but it is only interesting if OO design is the best way to model knowledge. The nearly complete failure of OODBMSs in the marketplace hints that this is not the case. The relational model, with its predicate-logic foundation, possesses the same expressive power as OO design without incurring the graph-theoretic complexities of OO models.
  5. @Chris's objections to the relational model on the grounds that it doesn't solve today's problems (hence the NoSQL movement) is completely off the mark. NoSQL means "No SQL", not, "No relational model". Unfortunately even proponents of the NoSQL movement seem to be quite clueless in this regard. SQL has deep flaws, many of which can be traced to its radical departure from the relational model. To say that we should abandon the relational model because SQL sucks is a rather blatant case of throwing the baby out with the bathwater.
  6. Failure to use an ORM does not triple the effort of building an application. This is a ludicrous claim, and even @Chris seems to be holding the back door open on it with a backhanded compliment to the codegen alternative. Codegen tools such as LINQ-to-SQL's sqlmetal are a perfect solution for anyone who isn't wedded to the dogma that the application's data model absolutely has to be different to the database's data model.

My own experience with ORMs has been that they work great in tutorials and cause endless pain and frustration in the real world. With LINQ-to-SQL fixing many of the problems that motivated ORMs in the first place, I see no reason to put myself through that kind of torture.

One major problem remains: the current crop of SQL databases doesn't offer any meaningful degree of control over the separation of physical and logical layers. The mapping from a table to stuff on the disk is largely fixed and entirely under the control of the SQL DBMS. This was not part of the plan for the relational model, which explicitly separated the two, and allowed for the definition of a consistent logical representation of data that could be stored on disk in a completely different structure than was suggested by the logical model. For instance, a system (or dba) would be free to physically denormalise — for performance reasons — a highly normalised logical model. Because SQL engines don't allow this separation of concerns, it is common to denormalise or otherwise torture the logical model through sheer necessity. As a result, logical models can't always be exactly as they should, and so the ideal of using the database as the purest representation of knowledge cannot be fully realised. In practice, however, designers generally stick to a canonical mapping from database to domain model anyway, because anything else is just too painful to maintain.

Noldorin
  • 144,213
  • 56
  • 264
  • 302
Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365
  • 19
    I am down voting you because I disagree with your argument that an ORM adds unneeded complexity and that yes you absolutely MUST separate your layers in software design. ORMs are very complex (if they are fully functional) because they solve a very complex problem. The reason ORMs are important is because with the support of an ORM you can correctly design an application in a way that you build your application independently of the database. Without using an ORM it is standard that the end result is the database will own the application and all associated changes will reverse up to the app. – Chris Marisic Apr 19 '10 at 23:23
  • 12
    When you have your database dictating design of your app you lose the ability to correctly model object orientated design and start letting a database dictate how you design an application which is absurd. I care nothing about the database. It is a persistent data store and nothing else. Using a database with an application is solely a means of having a persistent data store that can be queried in some fashion. This is the reason the NoSQL movement has gained so much traction recently because relational databases don't solve problems developers face. – Chris Marisic Apr 19 '10 at 23:26
  • 4
    The other prime factor is that by choosing to dumb down your application and just couple it to a database and datareaders (or worse datasets/datatables) you easily triple the amount of work required to develop an application. At this point you need to write all of the CRUD operations yourself. There is obviously tooling that can generate some of this for you but that's the backwards approach to software design and once again furthers the database will control the design of the application because most codegen tools are opinionated and will cause developers to alter their development to mesh – Chris Marisic Apr 19 '10 at 23:28
  • 1
    I just saw your responses to my comments, I fundamentally disagree with your assertions. The application is the purest definition of the business, and it should be modeled as such. You should build your application to exactly the specifications you have. The database after that is merely a durable store for the application. Once again, I fundamentally disagree with statements like "ORMs are just a canonical mapping onto the data layer (Tables Foo and Bar become classes Foo and Bar, and table FooBar becomes some kind of torrid affair between classes Foo and Bar). " – Chris Marisic Nov 12 '10 at 16:13
  • 1
    That statement is backwards, the classes Foo and Bar are not related to the database tables, the database tables of Foo and Bar EMULATE THE CLASSES. That is why Sql doesn't solve today's problems, all usage of RDBMS in conjunction with software applications are all efforts of getting the database to behave as if it were the classes inside the application directly. The places where RDBMS really fit are actions like ATM withdrawals, operations that are extremely fixed, transactional operations and aren't representing a deep object graph class. – Chris Marisic Nov 12 '10 at 16:16
  • @Chris: "That is why SQL doesn't solve today's problems, ..." This bit I agree with, but it ignores the tail-end of my answer. SQL fails because it diverges from the relational model, not just in logical/physical separation, but also in representing hierarchical and recursive relations, providing an extensible algebra, and many more aspects. If SQL had properly supported all that the RM is capable of, we wouldn't even be having this discussion. Apart from that one statement, everything else is unsubstantiated assertions. You say classes are fundamental. I say relations are. So let's test this. – Marcelo Cantos Nov 12 '10 at 22:56
  • 6
    Imagine a social networking site with users and groups in a many-to-many. In an object model, which owns which? The usual ORM solution is for Users to have a groups property, and Groups to have a users property. So, the boss comes along and says, "Make me a report of pairs of users that share more than one group!" Now, will you go to your object model and ask that question, or will you just whip up a quick self-join on the UserGroup table in your favourite DBA tool? (Lets even stipulate that you have a handy interpreter shell with your ORM schema already loaded up.) – Marcelo Cantos Nov 12 '10 at 22:57
  • 15
    The reason 99 out of 100 programmers will go straight to their SQL editor is that relations and operations on relations are the most natural way to think of knowledge. Knowledge is what databases store and manipulate, not objects, and knowledge is what you work with daily. OO just confuses the whole issue and has you thinking that PatientVisit, SecurityRevocation, StaffCount and UserGroup are all "things". The truth is that there are many classes of relation (aka kinds of facts) that don't make any sense as objects, but the knowledge we have of objects can always be represented as relations. – Marcelo Cantos Nov 12 '10 at 23:05
  • 2
    Addendum: In an ORM, UserGroup is not generally represented as an object, except when it is. The business application may only want to know who is a member of which group, and so UserGroup is just a behind-the-scenes table. But now the business wants to know when a user became a member and their standing in the group (noob, novice, journeyman, ...). UserGroup is no longer just a "relationship" between two classes; it is now a class in its own right, requiring changes to the User and Group classes. Two new fields have broken existing code that doesn't even use them. Not very pure. – Marcelo Cantos Nov 12 '10 at 23:52
  • There's clearly no bridge here. I fundamentally disagree with you and always will. – Chris Marisic Nov 15 '10 at 15:05
  • 3
    @Chris: Yes, there is a bridge. It's called the cold hard light of reality. If you can show that object models are at least as good at answering questions (aka queries) about the business as the relational model is, then that will clearly demonstrate OO's viability as an alternative to the RM for representing knowledge. If you can show that OO makes it substantially easier to ask questions, then you will have a strong case for OO replacing the RM entirely. – Marcelo Cantos Nov 15 '10 at 21:35
  • 5
    Of course, proving the OO's equivalence or superiority to the RM with respect to querying the database is only part of the story. You also have to demonstrate that OO is as good as or better than the RM at manipulation. How would an ORM do this: `UPDATE staff SET salary = salary * 1.1 WHERE (SELECT SUM(amount) FROM sales WHERE staff_id = staff.staff_id) > 1000000`? Or this: `INSERT INTO inventory SELECT serial_id, sku_id FROM refunds r WHERE NOT EXISTS (SELECT * FROM inventory WHERE r.serial_id = serial_id)`? – Marcelo Cantos Nov 15 '10 at 21:42
  • 4
    +1 Awesome post; very quotable. I'm collecting these types of answers to use when I get asked idiotic questions ("Why aren't you using an ORM? You're an idiot!") and am so taken aback by such a lack of awareness of the obvious that I can't articulate an intelligent response. – 3Dave Jan 10 '11 at 17:35
  • @Marcelo I find your arguments to be completely non compelling and unrelated. Relationships are just as inherently apart of OO design as they are in database designs they are just expressed in different way. I once again reiterate, I fundamentally disagree with you. We have no bridge. Same as your argument for querying data, I don't use OO to query a database, I use a database because that's it's purpose... to physically query the data. – Chris Marisic Jan 10 '11 at 19:22
  • 1
    @Chris: Something must have been lost in translation. What is ORM for, if not to, "use OO to query a database"? – Marcelo Cantos Jan 11 '11 at 01:18
  • 1
    @Marcelo an ORM is about separation of concerns. If you're dependent upon a database with handcoded (or even generated) sprocs you have an entirely separate application that has code that has to be maintained and versioned. Using an ORM is primarily about keeping all of the LOGIC inside the application instead of leaking out of it INTO the database. – Chris Marisic Jan 11 '11 at 14:27
  • 2
    @Chris: Sorry, but I can't infer a connection between your latest comment and my preceding question. I'm still stuck on, "I don't use OO to query a database." Say you use your ORM to apply a filter to an object collection and navigate from those objects to some child objects, thereby gaining accessing some subset of the data in the database that interests you for the present. What are you doing, exactly? I would call it, "[using] OO to query a database." Do you call it something else? Or do you not use ORM for that kind of thing? If so, then what *do* you use ORM for? – Marcelo Cantos Jan 12 '11 at 03:04
  • I obviously use those to query the database but that's just a different representation of a SQL query, it has nothing to do with OOD / OOP. Other than clearly internally in the ORM there would be design fostered to be able to convert it to raw SQL. But yes there are some advantages to it like being able to have strong reference to property names through lambda operators with the right tools instead of pure magic strings like SQL is. – Chris Marisic Jan 12 '11 at 15:18
  • 2
    @Chris: So, you don't use object-oriented design to query databases? I can't even parse that statement, other than to say, "Well, of course not; you use a query language." But that is entirely beside the point of this whole discussion. If I ask how you would performed the aforementioned operations (`SELECT...UserGroup...`, `UPDATE staff...`, `INSERT...inventory...`), then protesting that OO can do relationships too doesn't really cut it. These are simple, straightforward data management examples that ORMs ought to handle if they have pretensions of being the reigning data access paradigm. – Marcelo Cantos Jan 13 '11 at 00:38
  • I don't even know what you're arguing anymore. The point of an ORM is to ABSTRACT the database. That is the #1 ultimate purpose. There are lots of other benefits such as reducing the amount of code that has to be written, adding caching options, dirty tracking so updates only need to adjust values that changed instead of full objects and so on. – Chris Marisic Jan 13 '11 at 13:28
  • 4
    @Chris: What I've argued all along is that ORM sucks at the very thing it exists for: accessing and manipulating knowledge stored in a database. If "abstracting" away from the DBMS is so great, then how easy is it to do the operations I described? Here's some SQL for the first scenario: `SELECT a.userID AS user1, b.userID AS user2 FROM UserGroup a JOIN UserGroup b USING (groupID) WHERE a.userID < b.userID GROUP BY a.userID, b.userID HAVING COUNT(*) > 1`. Note that it doesn't even fetch the user or group tables. How much code would an ORM take, and how much data would it pull across the wire? – Marcelo Cantos Jan 13 '11 at 17:42
  • 1
    I can't even figure out what you're trying to accomplish there, but since you're just throwing random stuff out there I'll give a random answer back, atleast with NHibernate they have a full HQL alternative to SQL (h for hibernate) which you could write that near exact statement with even a couple less characters. But the reason why I wouldn't write that query in HQL is because whatever it looks like you're trying to do there is the result from a complete break down of your model / design more than anything if you need to do queries like that. – Chris Marisic Jan 13 '11 at 20:15
  • 4
    @Chris: HQL is a query language. It has "select", "join", "group by", "where", and a bunch of other stuff basically lifted from SQL. You use HQL when your object model fails to express what you want to say, and it amazes me how often an application's workload is inexpressible as navigation of object graphs. So we go to a language that strongly resembles SQL and ask it to do all the hard work, pretending that ORM wins. Pragmatically, that would be sort of OK, but my own experience suggests that HQL rarely works as advertised. I could be way off base on this, so I'm keen to see a real answer... – Marcelo Cantos Jan 13 '11 at 23:54
  • In this vein, here's a concrete problem, with no bias towards any particular solution or modelling paradigm. I want to write a simple social-networking app that can present a web page showing the 10 group-pairs with the most members in common and the 10 member-pairs that have the most groups in common. Can you outline the object model and database schema and suggest the kind of code that will let me do this with a minimum of data transfer across the wire? The equivalent SQL (http://pastebin.com/zgfqW1kr) transmits just two tables with three columns and ten rows each. – Marcelo Cantos Jan 13 '11 at 23:54
  • While you ponder that one, mull over this one: A sports clinic wants to track stats for various athletes of different types: runners, swimmers, cyclists, shot-putters, etc. For each type of athlete, they can compute a heuristic function based on the recorded stats to determine that type's risk of injury; a different heuristic function covers each type of athlete. How would you use OO to model this in an ORM? – Marcelo Cantos Jan 14 '11 at 00:14
  • The social networking question is reporting and should be done in a OLAP database not a transactional database, the 2nd one hinges entirely on the completely ambiguous "heuristic function" in question, since you note nothing about what exactly that's supposed to do your question isn't even answerable there. – Chris Marisic Jan 14 '11 at 14:23
  • 2
    @Chris: Does this de-scoping exercise mean that the HQL won't be forthcoming? And are you saying that it is impossible to even offer a basic outline of how the sporting example would be solved? It's not like I've asked you for a control system for the LHC. It is quite easy to define a basic SQL schema that works with a range of interesting heuristic functions without insisting on a detailed specification for the functions. – Marcelo Cantos Feb 09 '11 at 11:14
  • I don't even know the point you're arguing anymore. As far as I understand HQL it is a fully featured language that could express any query you want. At this point it's just an exercise in syntax. My argument is if you need to do SQL that's so complex that you need to use HQL to describe your goal is that your model itself already seems inherently wrong. That type of querying should be precomputed and the results able to be read from a flat source inside an application. The application shouldn't be responsible for dynamically producing those results unless the entire application is reporting – Chris Marisic Feb 11 '11 at 13:55
  • 1
    if the entire application is nothing but reporting, an ORM might not make sense since most reporting applications are nothing but drivers to allow you to feed parameters to an input and display a grid on the output. For applications like this that are mostly devoid of logic, the abstraction of an ORM probably isn't needed. ORMs are used for separating persistence responsibility from business domain logic. Trying to argue that with some arcane sql query that would never be sanely run against your live database you could produce something HQL doesn't describe is meaningless (if even possible). – Chris Marisic Feb 11 '11 at 13:59
  • 3
    @Chris: Arcane? It's a rather common requirement, actually. I have seen similar queries run against online databases comprising over 200,000 users, on pages that loaded in well under 1 s. Perhaps it wouldn't scale to the million or more mark, but that's just par for the course as everything gets bigger, and most sites simply never get to that size, anyway. OTOH, good caching infrastructure might let you scale beyond that while still avoiding an offline solution. Persistence is useless if you can't access data the way you want. What's more, OLAP doesn't handle the other scenarios I asked about. – Marcelo Cantos Feb 11 '11 at 22:20
  • Putting an object graph in a DB with plain SQL is just tedious, verbose and error prone. – Mike Braun Jul 19 '12 at 20:05
  • 1
    Brilliant answer. I've been against ORMs for a while, and this perfectly summarizes how I've felt for years. – Jon Haddad Jul 19 '12 at 23:49
  • +1, though I think the optimal solution is ditching relational databases altogether. NoSQL is the way of the future, and human obduracy towards old and "reliable" designers often hinders progress and future proficiency. In this case, very much so. I don't think the monstrosity that is SQL can ever truly be embraced by any usable modern language, and hiding his warts in a ORM is just hoping for the best, I feel. – Noldorin Jul 20 '12 at 00:40
  • @Noldorin: Thanks for the vote, but... There is little about NoSQL that is new, and you seem to be making the precisely the mistake that I warn about in point 5 in my answer: conflating SQL and the relational model. – Marcelo Cantos Jul 20 '12 at 07:40
  • @MikeBraun: Then don't. Your mistake is to think that one should begin with an object graph and then try and ram it into an SQL database. A database design should be based on the relational model; you can fit *that* into SQL (still not a perfect fit, but it can be done reasonably well) and then access the model as-is from the application layer. LINQ-to-SQL makes this final step very easy, but even without it, talking SQL is far less painful than the horror of pulling data out of an ORM (unless you can present solutions for the various queries that I ask about in the comment trail.) – Marcelo Cantos Jul 20 '12 at 07:47
  • I have to point out that many NoSQL supporters believe that NoSQL should be renamed to NoRel, precisely because it means "no relational model" rather than throwing out just SQL. [This](http://nosql-database.org/) mentions the non-relational almost immediately. Many databases created in them lacks a schema, let alone a normalised structure. – Muhammad Alkarouri Jul 20 '12 at 08:38
  • @MuhammadAlkarouri: Quite. "NoRel" better describes what the NoSQL movement is trying to do, and I admit my comment was a bit ambiguous. I was, in fact, trying to make the same point you make. My reference to their cluelessness was in reaction to the anti-relational-model stance taken by NoSQL proponents and was a commentary on the flawed reasoning generally given for abandoning the relational model. If they had stuck to criticising SQL and its flaws, then the both the term and movement would be on firmer ground. – Marcelo Cantos Jul 20 '12 at 09:34
  • @MarceloCantos: I would temper that a bit. The relational model does have its weaknesses; it is not a panacea. It is true that most of the reasoning out there for abandoning it is flawed. Still, there are some reasonable situations in which trading off the relational model for some data store with less consistency or better characteristics for semi-structured data is the better deal. – Muhammad Alkarouri Jul 20 '12 at 12:02
  • @MarceloCantos: No, you misunderstand. They are two separate horrors, where the relational model is partially responsible for the unwieldiness of SQL or similar DSLs. – Noldorin Jul 20 '12 at 13:07
  • @MuhammadAlkarouri: While consistency is an integral part of the relational model, how and when it is achieved isn't. There is nothing in the RM that makes it inherently incompatible with eventually consistent systems. Likewise, nothing in the RM prohibits or even hinders the storage of "semi-structured" data, whichever definition of that term you choose. In fact, a truly relational data store that cleanly separates the logical and physical layers would be the ideal medium for storage (NoSQL's strong suit) and manipulation (SQL's forte) of semi-structured and hierarchical databases. – Marcelo Cantos Jul 21 '12 at 07:13
  • @Noldorin: Can you point out specific instances of how the relational model informed poor choices in the design of SQL? – Marcelo Cantos Jul 21 '12 at 07:19
  • @MarceloCantos The relational model doesn't permit SQL to be too different in semantics from what it is. Complex joins, nested queries and updates, and many other tasks are quite cumbersome in SQL. There are some SQL-specific features (to each variant indeed) such as cursors, certain functions, table variables, that further add to the unwieldiness of the language, but are largely independent from the relational model. To me, a database DSL should either by a subset of the language consuming it, or a bytecode VM that is sufficiently generic to allow proper and efficient mapping to the host. – Noldorin Jul 21 '12 at 16:32
  • 1
    @Noldorin: SQL is indeed more awkward than it needs to be for those operations, but this is because it deviates from the relational model. Have you actually seen how such concepts are implemented in relation languages such as Tutorial D? More importantly, even in SQL, complex joins are far simpler and more readable than what you would have write with ORMs. If you disagree, then you are most welcome to present working ORM equivalents of the SQL I presented in earlier comments. – Marcelo Cantos Jul 21 '12 at 23:15
  • @MarceloCantos: As I said, I think the relational model is fundamentally flawed. I whole-heartedly embrace the concepts of object databases and above all graph databases, with subset-DSLs. – Noldorin Jul 22 '12 at 00:28
  • 1
    @Noldorin: What you or I *think* (or embrace) is of little consequence. Can you cite any facts to justify your claim that the relational model is fundamentally flawed? – Marcelo Cantos Jul 22 '12 at 02:23
  • @MarceloCantos I still come back to this question. Thanks. I'm doing a real world application in Java at the moment. It is in the design stage. It is a web application. I do not want to use an ORM. I also do not want to embed my SQL (no matter the database.) But now I am wondering what to do. If I don't embed and I don't use an ORM, how do I design the application? I don't put everything in stored procedures do I? Can you point me to a resource for Java design on this. You mention LINQ to SQL, so I was hoping to find something for other worlds. – johnny Jun 02 '14 at 01:56
  • @johnny: There are no good solutions out there. SQL isn't great, but it's the best there is right now. My recommendation would be to define a business layer that encapsulates all the embedded SQL your application needs. With a bit of up-front investment, you can auto-generate most of the CRUD. If you were on .Net, you could use something like LINQ-to-Entities 1:1-mapped to the database schema. (Frankly, I still prefer Linq-to-SQL, since it gives me pretty much all the bits I need, and none of the crap that I don't. But, being deprecated, it's a tough sell.) – Marcelo Cantos Jun 04 '14 at 04:32
  • @MarceloCantos Thank you again. I was going to use xml files, read by my homemade BLL or DAL. – johnny Jun 04 '14 at 14:03
49

In my experience with NHibernate it's a bit like Visual Basic: it makes easy problems really easy, but it also makes anything harder than that really hard or even completely impossible.

The basic idea is that ORM avoids having to write persistence code. There is a lot of duplication in such code, so it's very tempting to make that code generic, rather than specific to a particular business layer, and re-use it across projects. So far so good. For simple object hierarchies and business requirements this actually works really well. If your database changes, yes, you do have to change the ORM mapping files, but that's usually quite simple and you only have to make the change in one place - much easier than changing code that accesses the database.

The problem is that as your database and requirements get more complex the ORM finds it increasingly hard to keep up. So the ORM gets more and more complex. It also takes shortcuts, doing some things inefficiently, because it just isn't smart enough to figure out how to do it efficiently in all cases. What's more, because the whole idea is that it works transparently, you often can't see these performance problems until they become bad enough to affect the user experience. A related problem is that bugs are much harder to find, because you just don't know what's going on inside the ORM unless you debug it. (Yes, I've had to step through NHibernate code and it's no picnic!)

So you start bypassing the ORM for some things and use SQL directly instead. Of course, you then have to make that code work with the code that does use the ORM, which is more work. You end up writing code to load and save some objects manually and to somehow work that into the ORM code. Eventually you start wondering if the ORM is creating more work for you than it's saving - not to mention the performance and bug hunting headaches.

So if you're writing a very simple application, the kind you find in a tutorial, ORM will do a good job. If it's more complex than that then I think it's not worth it. Of course, for a simple application the absolute amount of time saved will be small as well. My conclusion: just don't bother with ORM. ORM is the path that leads to the dark side.

EMP
  • 59,148
  • 53
  • 164
  • 220
28

Prior to reading this I often wondered if any others really bothered to understand the impact an ORM tool has on a project. @Evgeny, @Marcelo Cantos, and @Jimmy B put this to rest.

In short, they are dead on with most of the issues that surround ORM tools. There is only a couple that they either haven't covered or haven't covered enough.

First, usage of an ORM does not mean less code. It might mean less SQL, but it certainly doesn't mean less code. Along these lines, tool generated code can be wrong. Worse, compensating for bad generated code is an exercise in frustration.

Second, ORM tools do NOT mean you don't have to understand SQL. To put this another way, you must know SQL to be an effective programmer (there are exceptions like the embedded guys). The queries (both type and number of) emitted by these tools just aren't good enough from a performance or resource perspective. If you already have to know SQL, why shackle yourself?

Third, ORM tools do NOT save time. You will spend as much (if not more) time beating your ORM tool of choice into submission to take care of any application of decent size. To add insult to injury, when you are done you will see that the quality of the queries are generally worse than if you had done it yourself. Point is ORM = more time spent on the project, worse outcome.

Fourth, DBMS independence is generally a waste of time. Most applications will use exactly one DBMS over it's life; whether it's Oracle, SQL server, MySql, whatever. The application will be much better off it is able to take advantage of the features the DBMS provides. Being DBMS agnostic means that you'll have to limit yourself to sub par queries.

Fifth, not everything has to be an object. This is an important thing to note. We are often asked to show a particular set of data on a page. More often than not this means joining data from two or more tables. Should your app have to create and instantiate all of those objects just to display some data? Or are you better off just executing a query and emitting the data straight to the screen/browser in the format of your choice?

ORM's add a LOT of overhead to even the simplest things. Most ORM's will generate multiple sql queries to perform even a simple UPDATE on a table.

Sixth, and the most important issue in my mind: ORM's decrease your security. Sure you can use ORM's with s'procs; but most people don't. Nearly every app I've seen that leveraged an ORM exposed the database in such a way that if the site is cracked the entire database can be easily killed or pilfered. ORM tools generate SQL on the fly. This means they need direct table access. This means that if your app is compromised, the hacker will have direct table access. This means that you have effectively removed at least one layer of security from your application.

NotMe
  • 87,343
  • 27
  • 171
  • 245
  • 4
    +1 for rounding out some of the points not called out elsewhere. I hadn't even considered the security angle. One minor nit-pick: in a couple of places, you referred to *database*, where you really meant *DBMS*. One of the factors contributing to the mess the industry is in, wrt knowledge management, is a terrible lack of precision in the use and interpretation of terms (e.g., conflating "table" and "relation", or worse, conflating "relation" and "foreign key"). – Marcelo Cantos Jan 11 '11 at 01:26
  • 4
    +1 I especially agree with "database independence is generally a waste of time". It's a nice ideal, but never works in practice. The security angle is an interesting one, but I think any application that needs to do CRUD can't protect the DB from itself - and that would be the vast majority of applications. – EMP Jan 11 '11 at 05:29
  • @Marcelo: updated with better precision on terminology. You're right. – NotMe Jan 11 '11 at 14:52
  • @Evgeny: Securing apps is generally an exercise in making things as difficult as possible. For our systems all data operations are handled in s'procs. The first thing they do is test for authorization to perform the action. The actions are limited in scope to at most a handful of records. Which means if the app layer is hacked then they will have to capture an admin account in use, then spend a lot of time calling s'procs to pull / modify / or delete data. This increases the effort involved to a point that we would be able to identify and track down the hacker. – NotMe Jan 11 '11 at 15:00
  • @Evgeny: In this case it is simply about slowing them down enough to be caught. However, if the app had full access to the tables to run any ad hoc query a hacker could be in and gone before someone could even respond to a warning from the IDS. – NotMe Jan 11 '11 at 15:01
  • 1
    Security: I wouldn't advocate the use of ORM anywhere where SQL security was used. – BonyT Jun 28 '11 at 09:27
  • But in my experience ORM tools do save you code - a lot of code! NHibernate with Automap and a well designed schema, and a rich Abstract repository class, and I write hardly any data related code. So that's points 1 & 4 challenged since less code means less time. – BonyT Jun 28 '11 at 09:30
  • I also have no problem in excluding certain operations from NHibernate - need a complex report done that's easier in SQL. Why not add a non-ORM method onto your Repository and call a sproc? ORM isn't meant to limit you - it's meant to take away the donkey work from CRUD operations. – BonyT Jun 28 '11 at 09:31
  • 1
    Agree with points 2 & 4 though. Overall I would say that one could say similar things about many coding tools - Generics, jQuery, multithreading, SOA via WCF etc etc. All very useful tools/techniques in the right hands. However, I have seen them all abused producing difficult to maintain/unecessarily complex code through a lack of understanding in how to use them. ORM's don't make you a good coder - you probably need to be a better coder (or have one on site) to use them - it definitely raises the intelligence requirement on new hires, but on the right project, it's a boon. – BonyT Jun 28 '11 at 09:35
  • @BonyT You can use Automap without NHibernate to get the same amount of savings. Or even skip objects entirely and just use datasets. – Jonathan Allen Jul 19 '12 at 19:48
  • @Jallen - On the ORM topic I think we'll have to agree to disagree - but if you're still using datasets in anything except a single tier app then I hope I never have to work with your code! – BonyT Jul 19 '12 at 20:06
10

I realize this question was posted a while ago, but I've wondered the same thing as johnny. I've seen Hibernate used on several large projects by intelligent people, and in every case, it was an unmitigated disaster. In my experience, the single most complicated and performance impacting area of most enterprise applications is between business layer and the database layer. This is part of why we add a data access layer to try to encapsulate the database interactions into manageable chunks.

The biggest arguments I've seen to use ORM are that they "reduce hand written code" and provide an abstraction layer that separates business logic from the data access. I assert that neither of these are true in practice except in very simple cases.

To make Hibernate (and most other ORM tools) work, we either create a hibernate mapping file which documents all the database and object interactions, or we use annotations to document the same relationships. In one case we moved our code to an xml configuration file that is harder to test, yet no less complex. In the other, we distribute the logic of how to interact with the database all over the domain model. The point is, while we've written less actual "code", moving code to configuration files or annotations != "less code". It simply moves the complexity from the code, where we can control it directly and mitigate it, to a third party tool with far less control.

The ORM abstraction layer that is supposed to separate the business/domain layer from the database layer tends to have more subtle effects that counteract this "separation". How many projects have you seen where the ORM layer affects the design of the object model and/or the database in a way that would be considered less than ideal? To use a poor physics analogy, assume your business layer, ORM layer, and database layer all have mass. The mere existence of the ORM layer between the other to tends exert a force that changes and warps the other layers. Have you had to introduce a primary key object that doesn't quite fit in your business model because the ORM layer needed it? Have you had to adjust your database structure to accommodate a particularly complex object graph model because the ORM tool can't handle it otherwise? Taken to extremes, the presence of the ORM layer can warp the entire perspective of how database interactions should work. Instead of a service layer that handles persisting object graphs, it can devolve into creating individual data access layer objects for each domain objects, as if they live in isolation. I've seen all these scenarios in varying degrees. Perhaps it's inexperience with the ORM toolset. Perhaps it's a bad database structure. I doubt it. Everything I've seen points to the ORM solution being inadequate.

If you accept my assertion that the data access layer is one of complexity, highly prone to performance bottlenecks, why should I consider adding in a tool that doesn't achieve it's objectives of less code and separation, and at the same time negatively affecting the structure of the other layers of my application?

Jimmy B
  • 101
  • 1
  • 3
  • "In the other, we distribute the logic of how to interact with the database all over the domain model." Isn't that where's it's supposed to be in the MVC/MVVC setup? When you say Annotations, I assume you're referring to the JPA/JPA2 annotations used by Java ORMs. JPA was developed so that not only is your model DB independent, but JPA is also implementation dependent... I could be using EclipseLink or Hibernate and the classes don't need to know which. – Powerlord Jan 10 '11 at 16:56
  • 1
    From the way I worded it, I made it sound like using Annotations on domain objects is a bad thing. That's not really what I was trying to convey. To your point, it can absolutely be appropriate to do so. And yes, I was referring to the JPA/JPA2 annotations... I really should have stated that explicitly. What I was really trying to point out is that using ORM tools (or JPA implementations) is transforming the complexity of the domain model <-> database model relationship from one form to another, not necessarily reducing it. Sadly, in my experience, this often increases it. – Jimmy B Jan 10 '11 at 18:28
  • Implementation independence in terms of libraries isn't important. You aren't going to be changing that very often, if ever. You will, however, be changing your tables and object models a lot. Hopefully in ways such that a change to one doesn't affect the other. – Jonathan Allen Jul 19 '12 at 19:54
8

I responded thoroughly to the answer by @Marcelo Cantos however I will summurize the main benefits of using an ORM.

Persistence Ignorance (PI) and Domain Drive Design (DDD)

A ORM lends itself perfectly to both of these overall design patterns. For correct object orientated design you will work with hierarchical and polymorphic objects for expressing how data flows inside your application. With a good design you will frequently strive for POCO objects (plain old C/C# objects, I've seen other definitions of this word) because if I have a Person that has a List I should have just that. I shouldn't have a DataTable of persons and a DataTable of addresses that I somehow force to work with my application. Along with that I shouldn't need to tie tons of database specific logic to my objects, why should the FirstName field of my person need to be have something like [ColumnName("First_Name")] [Length(255)] [DataType(Types.Nvarchar)] or any other assortment of crazy attributes or code that defines how many database exists forced into my domain design?

Less Hand Written Code

There is a substantial reduction in the number of lines of code written when you remove the need to write an Select, Insert, Update and Delete statement for every single object in your application to save it to the database. This leaves you with only the need to write queries that mean something. Also many ORMs (like NHibernate) will include a language that is layered on top of SQL which is more defined to interact with and can be less syntactically filled of hoops.

The time this shows up fullest is consider an application that has a UserTable that is linked to every single object and for some reason you HAVE to change the primary key name or type. At this point you will potentially need to alter every single stored procedure in the database where with a correctly implemented ORM solution you will only need to alter a few configuration mappings (or possibly none) and it's done.

Bill K
  • 62,186
  • 18
  • 105
  • 157
Chris Marisic
  • 32,487
  • 24
  • 164
  • 258
  • 5
    I was going to vote for this, but taking less hand-written code as an advantage is a huge problem for me. Generated code is evil. There tends to be reams of it, and it still has to be maintained. can't promote crap like that. – Bill K Nov 12 '10 at 00:36
  • 2
    @Bill you're misunderstanding what an ORM does in that sense, it doesn't just "generate code" the way that you can use StronglyTypeDataSetAdapters or CodeSmith etc it dynamically creates the underlying sql that needs to execute on the database to execute the physical operation while completely abstracting that. Using an ORM is absolutely the right decision in removing boiler plate code for handling basic CRUD operations. Using an ORM there is no generated code to maintain, however there will probably mapping/configuration that is used to describe your database in any ORM. – Chris Marisic Nov 12 '10 at 16:03
  • 3
    @Chris your repeated assertion that the database is just a persistent storage system is untrue. Database servers tend to be very, very good at, say, querying data, and many tasks are more efficiently and more easily implemented in SQL than in the application code. If you're that uncomfortable with SQL, then go your own way, but don't ignore the benefit of keeping the database code WITH the database! – 3Dave Jan 10 '11 at 17:46
  • 1
    Logic should not occur in the database. Only querying should occur in a database. – Chris Marisic Jan 10 '11 at 19:17
  • Querying requires logic. – 3Dave Jan 10 '11 at 19:48
  • Wrong, querying requires a set of values that are irrespective of logic. – Chris Marisic Jan 10 '11 at 19:54
  • 5
    Uh. Saying "Give me these give things that match this criteria" *is* logic. Also, logic to perform validation, etc. that is related to queries but not, in itself, a query, should live there. Having app code go check relationships, etc is pretty lame. – 3Dave Jan 10 '11 at 20:01
  • If all you are doing is single table updates you can code-gen stored procs just was easily as you code-gen an ORM. And that generated code can do application specific stuff like set "LastModifiedby" fields, something a generic ORM wouldn't understand. – Jonathan Allen Jul 19 '12 at 19:51
6

The basic benefit of using ORM tools is to facilitate the principal of separating the business logic from the data access in a multi-layered application. If you can successfully build a data access layer that is responsive to changes in the database (by changing your mapping), there is less overall code for you to have to muck around with when changes are made.

Separation of the layers is typically the goal of 3 tier or n-tiered applications, and ORM is a good method of doing that.

TheTXI
  • 37,429
  • 10
  • 86
  • 110
  • 4
    I really don't understand this argument. Using an ORM effectively moves your queries and db code from the database server into your application code - that's integrating concerns, not separating them. Case in point: a query change requires redeploying the app, whereas a stored procedure change can be done without touching it. – 3Dave Jan 10 '11 at 17:08
  • 1
    @David Livel, when would you change a CRUD SP without also changing the code-base?? ill tell you when, all those times bugs are introduced because someone forgets one or the other because THE SAME concern is in two discrete systems. – jenson-button-event Feb 27 '12 at 17:28
4

Primary driver: less overall code to manage/maintain

Srikar Doddi
  • 15,499
  • 15
  • 65
  • 106
  • 5
    It seems like more to me. That's the reason for my question. – johnny Apr 17 '09 at 15:24
  • Maybe more - but a lot of it can and will be generated, doesn't need to be manually written, and you get to work with OBJECTS vs. bare data rows and data fields. That's the biggest plus for me. – marc_s Apr 17 '09 at 15:31
  • 2
    many people believe in persistence ignorance, this way Objects know how to load and save themselves. – Srikar Doddi Apr 17 '09 at 15:43
  • 2
    @johnny with a tool like NHibernate there is a rather sizable addition in an initial setup to a project but with the appropriate scaffholding and initial design considerations added to the project it allows you to basically magically create any object structure you wish and then perform all of the CRUD operations against it without writing a single line of code. You need to consider the thousands of lines of Sql you will write when not using an ORM. – Chris Marisic Apr 19 '10 at 23:30
  • -1 This doesn't make sense. The queries have to go somewhere. You can't perform any operation in software "without writing a single line of code" - whether the query is in SQL, LINQ or calls into an ORM, you're going to have express what you want *somewhere*. – 3Dave Jan 10 '11 at 17:13
  • 1
    @David Lively you're just wrong. Using the right ORM can massively reduce your code. Using tools like FluentNHibernate you describe your database in terms of conventions so you don't need a godlike mapping layer. Now since software lets you use OO design it lets you re-use code generically unlike databases. I can write a single generic repository model that will give me Insert, Update and Delete for any of my objects by simply telling my inversion of control container I want one. Past that the only thing left to write is queries themselves because those need expressed somehow. – Chris Marisic Jan 11 '11 at 14:32
  • 2
    If all you're using the database for is object persistence (which is a waste of an excellent resource), then building a persistence/proxy layer is a waste of time, as you point out. However, if you're going to put the power of a good database server to work for you - and OH GOD WHY wouldn't you want to - things are not so clear-cut. Stored procedures are wonderful, SQL CLR assemblies rock, and every time I've had to expose a data layer to a different app written in a different language by another department, I've minimized logic reimplementation by placing it in the database. That means $$$. – 3Dave Jan 11 '11 at 23:22
  • 2
    @David I thank god I don't work in your shop and that I'm in charge of mine! Your solution is completely and utterly unscalable, unless you want to spend $100,000s on hardware and sql server licenses. The correct solution would to have a web service sit on top of the database and all relying parties consume the webservice. The webservice can employ aggressive caching and/or load balancing to allow the single database to service a near infinite amount of growth if it's a read primary datafeed. – Chris Marisic Jan 13 '11 at 20:18
2

The question that I haven’t seen anyone address is what problem or problems ORMs are supposed to solve. The problem that ORMs are supposed to solve deal with the disconnection between application side code and the database and the amount of time developers spend with database concerns. The disconnection between the database and application code refers to having to run the application to realize that the code written referenced to an invalid column. ORMs are supposed to close this gap making for a model in which the database, application, and data move together; I compile I know code is out of sync (provided I keep my Model up-to-date).

I’ve used 3 different ORMs (EF, LINQ to SQL, and N-Hibernate), on various size projects from small to large enterprise applications. In addition I’m no stranger to going about it with ADO.NET; DataReaders and mapping to classes, DataSets and various generation tools. I have seen good and bad implementations in the 3 different ORMs and with no ORM method. The majority of problems I’ve seen go back to anti-patterns, and not understanding limitations of a particular ORM. The following article (Anti-Patterns To Avoid In N-Tier Applications) does a nice job of highlighting many of these Anti-Patterns. Even the best of software architects, developers, and just smart people have participated in their share of Anti-Patterns before they discovered a design pattern and or the value of certain design principles that solved the problem created by the Anti-Pattern.

Not knowing your tool is another issue because this is where issues with performance come in. It’s clear many are unsure of the performance differences between Dynamic SQL and stored procedures in respect to executing database logic such as CRUD operations. Well the verdict is in and Dynamic commands are proven to be just as efficient as their stored procedure counterparts. Both have advantages and disadvantages. The key is knowing what they are and selecting the appropriate choice for the situation.

Brian
  • 6,910
  • 8
  • 44
  • 82
LCarter
  • 473
  • 7
  • 13
1

If all I get from my ORM is to save me from the need to maintain stored procedures then that is good enough for me.

However there's much more in that an ORM allows us be free of the hostage-like grip database schemas impose on the design of our code. Things are much simpler when I can model my code exactly like the real world, and I can still do this with a (good) ORM which helps (and hides) the mapping of a potential unsightly legacy db with terrible naming conventions into a structure that means something and not care about redundant code like this everywhere:

using (SqlWrapper sql = SqlWrapper.Create(WrapperConnectionType.ShopNet, "sStore_InsertUpdate_v4"))
            {
                sql.AddParameter("StoreId", StoreId);
                sql.AddParameter("StoreName", StoreName);
                sql.AddParameter("Region", Region);
                sql.AddParameter("PostCode", PostCode);
                sql.AddParameter("Tel", Tel);
                sql.AddParameter("Email", Email);
                sql.AddParameter("RegionId", RegionId);
                sql.AddParameter("MapImage", MapImage);
                sql.AddParameter("ShopImage", ShopImage);
                sql.AddParameter("Visible", Visible ? 'Y' : 'N');
                sql.AddParameter("TazEnabled", TasEnabled ? 'Y' : 'N');
                sql.AddParameter("Latitude", Latitude);
                sql.AddParameter("Longitude", Longitude);
                sql.AddParameter("StoreOpeningDate", OpeningDate);
                sql.AddParameter("CustomerNo", CustomerNo);
                sql.AddParameter("ReserveAtStoreEnabled", RasEnabled);
                sql.AddParameter("OpeningHoursId", OpeningHours.Id);
                sql.AddParameter("AddressLine1", AddressLine1);
                sql.AddParameter("AddressLine2", AddressLine2);
                sql.AddParameter("City", City);
                sql.AddParameter("District", District);
                sql.AddParameter("County", County);
                sql.AddParameter("CountryCode", CountryCode);
                sql.AddParameter("GoogleCategories", GoogleCategories);
                sql.AddParameter("GooglePlacesEnabled", GooglePlacesEnabled);
                sql.AddParameter("ManagerName", ManagerName);
                sql.AddParameter("MapZoomLevel", MapZoomLevel);
                sql.AddParameter("IpAddress", IpAddress);
                sql.AddParameter("FlibbleEnabled", FlibbleEnabled);
                sql.AddParameter("RegionalManager", RegionalManagerId);
                sql.AddParameter("ShutlLogin", ShutlLogin);
                sql.AddParameter("ShutlPassword", ShutlPassword);
                sql.Execute();
            }

and lets eradicate (but not forget) these type of battles:

System.IndexOutOfRangeException
at System.Data.SqlClient.SqlDataReader.GetOrdinal(String name)

The argument for me doesn't have to be any more complicated than that, I get a couple of nice things and something awful is taken away. Nuff said, Next!

No one is arguing that an ORM is a 100% replacement for everything traditional. It won't be a great tool for writing complex reports, for that use SPs and views, and use NHibernate to call them natively and map them automatically to your c# entities. Great, still all the power of SQL and no crappy mapping code.

Be gone into the darkness ye storer of 0s & 1s and come hither ye light of wholesome c# weltanschauung.

jenson-button-event
  • 18,101
  • 11
  • 89
  • 155
0

1 advantage you get is that your data layer is separated from the object layer, so when you have multiple applications/projects dependent on that layer you change it once in the ORM and all applications/projects that reference the object layer don't have to change, where as without it you would have to make changes in all projects.

chrishawn
  • 478
  • 1
  • 4
  • 12
  • 2
    but if I change the database structure don't I have to change everything not just what you described? – johnny Apr 17 '09 at 16:19
  • with automapping, if e.g. I add a new column, if i wish to write to that column i simply add a new property to my class with the same name and by Jove, convention saves the day. nothing more nothing less – jenson-button-event Feb 27 '12 at 17:23