Object-relational mapping, in the purest sense, is a programming technique that supports the conversion of incompatible types in object-oriented programming languages, specifically between a data store and programming objects. You can use an ORM framework to persist model objects to a relational database and retrieve them, and the ORM framework will take care of converting the data between the two otherwise incompatible states. Most ORM tools rely heavily on metadata about both the database and objects, so that the objects need to know nothing about the database and the database doesn’t need to know anything about how the data is structured in the application. ORM provides a clean separation of concerns in a well-designed data application, and the database and application can each work with data in its native form.
TIP: Nicknames and acronyms used for “object-relational mapping” include ORM, OR/M, and O/R mapping. Although ORM seems to be the term most commonly used in the .NET world, you’ll often see the others in books and articles. We’ll stick with ORM, mostly because it is the easiest to type!
The key feature of ORM is the mapping it uses to bind an object to its data in the database. Mapping expresses how an object and its properties and behaviors are related to one or more tables and their fields in the database. An ORM uses this mapping information to manage the process of converting data between its database and object forms, and generating the SQL for a relational database to insert, update, and delete data in response to changes the application makes to data objects.
ORM performs the rather amazing task of managing the application’s interactions with the database. Once you’ve used an ORM’s tools to create mappings and objects for use in an application, those objects completely manage the application’s data access needs. You won’t have to write any other low-level data access code. Strictly speaking, you could still write low-level data access code to supplement the ORM data objects, but this adds a significant layer of complexity to an application that we’ve rarely found necessary when using a robust ORM tool. It is better to stick to one or the other and keep the application simpler and more maintainable.
There are a number of benefits to using an ORM for development of databased applications and here’s four:
- Productivity: The data access code is usually a significant portion of a typical application, and the time needed to write that code can be a significant portion of the overall development schedule. When using an ORM tool, the amount of code is unlikely to be reduced—in fact, it might even go up—but the ORM tool generates 100% of the data access code automatically based on the data model you define, in mere moments.
- Application design: A good ORM tool designed by very experienced software architects will implement effective design patterns that almost force you to use good programming practices in an application. This can help support a clean separation of concerns and independent development that allows parallel, simultaneous development of application layers.
- Code Reuse: If you create a class library to generate a separate DLL for the ORM-generated data access code, you can easily reuse the data objects in a variety of applications. This way, each of the applications that use the class library need have no data access code at all.
- Application Maintainability: All of the code generated by the ORM is presumably well-tested, so you usually don’t need to worry about testing it extensively. Obviously you need to make sure that the code does what you need, but a widely used ORM is likely to have code banged on by many developers at all skill levels. Over the long term, you can refactor the database schema or the model definition without affecting how the application uses the data objects.
One potential downside to using an ORM is performance. It is very likely that the data access code generated by the ORM is more complex than you’d typically write for an application. This is because most ORMs are designed to handle a wide variety of data-use scenarios, far more than any single application is ever likely to use. Complex code generally means slower performance, but a well-designed ORM is likely to generate well-tuned code that minimizes the performance impact. Besides, in all but the most data-intensive applications the time spent interacting with the database is a relatively small portion of the time the user spends using the application. Nevertheless, we’ve never found a case where the small performance hit wasn’t worth the other benefits of using an ORM. You should certainly test it for your data and applications to make sure that the performance is acceptable.
There are a number of ORM tools available for .NET applications (see the “List of object-relational mapping software” topic in Wikipedia in the .NET section for an exhaustive list). Before Microsoft introduced Entity Framework, the open source NHibernate was probably the dominant ORM tool. NHibernate is ported from Hibernate, a Java ORM tool that has been available for years. But because Microsoft now bundles Entity Framework with the .NET Framework and incorporates extensive support for it in Visual Studio, Entity Framework has become the dominant ORM in the Microsoft development world.