With LINQ-to-SQL Every Application Can Have an O/RM

Published: 21 Apr 2008
By: Dino Esposito

Dino Esposito talks about LINQ-To-SQL as an O/RM tool.

Introduction

Many developers and architects wonder how Microsoft could come up with two analogous projects—LINQ-to-SQL and Entity Framework (EF)—with so many key design differences. The point is not much with the overall scope and features—clearly larger and broader in EF—but with the idea behind the products. It’s like if two different teams devised both frameworks, each implementing their own vision of things. With a bit more of spice, one could say that it’s like using both hands for accomplishing a task. But if the left hand doesn’t know what the right hand does, you can reasonably expect two different results rather than just one in perhaps half time. Believe it or not, this is just what happened with LINQ-to-SQL and EF. The technologies were originally developed by different divisions, living in different buildings. Each was designed from the ground up by different teams of architects and got a unique vision and perspective. Today EF is still in Beta and will be a version 1.0 released product with SP1 of .NET Framework 3.5 shipping later this year. LINQ-to-SQL reached the rank of version 1.0 just a few months ago. What can we expect for the future? And, more importantly, are we missing something about LINQ-to-SQL for the present?

EF and LINQ-to-SQL at a Glance

As I see things, LINQ-to-SQL was devised in the developer division to be the clever and powerful successor to typed DataSets. It was created to provide a record-based object model and let developers work with data at a more conceptual level, while using LINQ facilities for queries. At a first (and quick) look, I wouldn’t call LINQ-to-SQL an O/RM tool; I would rather call it an object-oriented replacement for the ADO.NET API. So I would rather use LINQ-to-SQL to build the data access layer (DAL) of a multi-tier system. And, more importantly, I would rather consider the entities that LINQ-to-SQL kindly generates for me just plain data-transfer objects (DTO).

EF, on the other hand, is more ambitious and geared towards the definitive resolution of the mismatch between the conceptual model of data and relational storage. EF comprehends a logical schema made of entity types and entity sets and exposes it through .NET objects and Web services. EF is recognized to be a fully-fledged O/RM tool and closely compares to popular tools in the industry such as NHibernate or Genome. Understanding the EF’s main purpose in life is, therefore, relatively easy and unquestionable. EF serves many purposes, but one of these is certainly acting as an O/RM tool.

What about LINQ-to-SQL, though? Is it really only a smarter instrument for implementing a data access layer? Or is it something more and somehow different? And if it’s something different from a just a DAL API, why on earth is Microsoft having two similar products that overlap to some extent, but also have key design differences? What’s the rationale? Is there really a rationale?

What’s the LINQ-to-SQL’s Main Purpose in Life?

My idea is that there’s just no rationale behind the choice of having two similar products that differ and overlap in various areas. The truth is probably much simpler and has merely to do with independent results obtained by independent groups. Those who consider LINQ-to-SQL just a DAL API are probably subliminally assuming that there has to be a rationale in the choice of having EF and LINQ-to-SQL at the more or less the same time on the same market. If you try, for a moment, to release this convincement and look at LINQ-to-SQL without being biased by the notion you may have of EF, you’ll likely admit that, well, LINQ-to-SQL can also be seen as a simplified O/RM tool. Probably not the tool you would use in a complex and sophisticated enterprise project, but an excellent tool to use in order to come up with a good design also in relatively simple applications. Hence, the slogan of this article: “every application can have its own object/relational mapper.”

In the future LINQ-to-SQL will likely be managed by the same group responsible for EF; in this way, the two products can evolve according to a unique set of guidelines. So what today are baffling differences may hopefully be smoothed out tomorrow, in the space of a new release. In this perspective, I really tend to consider LINQ-to-SQL as the poor’s man O/RM tool, with some clear limitations but also an explicit contract that everybody can read and understand, if not subscribe.

LINQ-to-SQL as an O/RM Cheat Sheet

What are some key features that a serious O/RM tool must have? Here’s a quick list. (If you feel I’m missing some important ones, don’t hesitate to comment.)

  • Ability to map an entity model to a storage layer
  • Support for Plain-Old-CLR-Objects (POCO)
  • Implementation of internal strategies for fetching, tracking changes, and object identity
  • Support for a query language

First off, an O/RM tool must be able to map its own entity data model to one or more columns in one or more tables. Mapping should ideally be saved to XML or expressed through attributes that decorate classes. LINQ-to-SQL clearly provides this feature.

Ideally, in an O/RM tool you should not feel bound to inherit your domain classes from a given base class or anything similar such as implementing a given set of interfaces or using ad hoc factories. Such plain objects go under the name of POCO and are objects that don’t need any extra code to behave in a given environment. POCO objects are persistence-ignorant and don’t know how the host framework will persist them. At least in the current release of EF, objects are not POCO. LINQ-to-SQL objects, instead, are essentially POCO even though you’re forced to using built-in types for collections of entities.

There’s a nice designer for LINQ-to-SQL that you get in Visual Studio 2008. The availability of such a tool makes it seductive to auto-generate the model through the designer. In this case, you have to start from a connection string, thus making the design of the domain model inherently table-oriented.

As in my previous article, lazy loading, identity map, unit-of-work, and optimistic offline lock are all patterns that the nerve center class of LINQ-to-SQL fully implements. This class is DataContext.

Finally, LINQ-to-SQL supplies a made-to-measure object-based query language that has the LINQ syntax applied to an ad hoc queryable type—collections exposed by the DataContext type.

On the other hand, LINQ-to-SQL doesn’t support multiple databases like, say, NHibernate or EF. It is, and will remain, bound to SQL Server. Likewise, LINQ-to-SQL is a limited O/RM because it doesn’t support fragmented entities, namely entities that are mapped to multiple tables. Furthermore, LINQ-to-SQL doesn’t support query caching.

In the end, LINQ-to-SQL is not certainly a fully-fledged, ultimate O/RM tool. It’s simple, but powerful enough to serve as an O/RM in wide range of situations where you wouldn’t even consider an O/RM otherwise. If you don’t need to be database independent, and can default to SQL Server, LINQ-to-SQL may help you getting an excellent object model, free implementation of transactional updates, lazy-loading, object identity, caching, and overall extensibility. In light of this, every application can afford and benefit of an O/RM tool. With LINQ-to-SQL used as an O/RM you should pay a bit of attention at how you move data across the tiers of your system. LINQ-to-SQL gives you entities that it manages through the DataContext class. You have no free data-transfer objects and original entities are attached to the native context.

Generalizing the Domain Model

The LINQ-to-SQL designer takes a connection string and generates a set of plain .NET classes with no dependencies on other framework classes. Here’s a sample designer-generated entity class:

The code is excerpted from a northwind.designer.cs class that the Visual Studio 2008 designer has created from a connection to the Northwind database. The code snippet is clearly incomplete, but illustrates the key characteristics of the LINQ-to-SQL entity classes. Here are some key facts:

  • Entity classes are partial meaning that you can add more properties and logic by simply adding a second (or a third) partial class to the project, or as an external assembly;
  • Attributes are used to decorate class and members and map to storage fields;
  • The set modifier contains some extra code that is the direct offspring of the implemented interfaces. It’s an extra feature, though, and not bound to the underlying framework. In other words, it can’t be considered as a symptom of not being a POCO;
  • The Orders property must be an EntitySet<T>. This is the only constraint in LINQ-to-SQL with regard to being a POCO;

The EntitySet class essentially provides the engine for lazy loading and takes care of relationships of type one-to-one and one-to-many. It is little known that you can even drop the pre-built support for EntitySet in your LINQ-to-SQL domain classes and replace occurrences with plain List<T>.

If you drop EntitySet, though, you lose free support for lazy loading. At the same time, the framework provides you with programmatic tools for taking loading under control. Methods to look at are AssociateWith<T> and LoadWith<T> on the DataContext class.

Here are a couple of interesting posts on the theme of LINQ-to-SQL and POCO:

Summary

In the past few months, I’ve been giving different answers to the same question about the role and overall purpose of LINQ-to-SQL. Is it for the DAL? Is it an O/RM? And based on that, I assisted to forms of religious wars between crowds of developers. The roles of LINQ-to-SQL and upcoming EF are certainly more blurred than one may think at first. As a matter of fact, LINQ-to-SQL provides a lot of facilities for setting up quickly and effectively a DAL. But it contains more—a lot more. It’s not the perfect and most powerful O/RM, but if you open your horizons a little bit, it can serve you as an O/RM and help you much more than you may think. Its object model can be extended and manipulated to become a true POCO domain model and go beyond the boundaries of the data access layer. Once you have that, why shouldn’t you consider LINQ-to-SQL as a simplified O/RM?

About Dino Esposito

Sorry, no bio is available

View complete profile

Top Articles in this category

Polymorphism and Encapsulation
Polymorphism and encapsulation are two big words in OO development, and are also a fundamental concept of software development. This article will demystify these concepts by showing you some real world examples.

Introducing LINQ – Part 1
Introducing LINQ is the first part of a series of articles on Language Integrated Query (LINQ). This series will cover the core essentials of LINQ and its use with other technologies like ASP.NET, Win Forms and WPF.

Writing an ActiveX control in C#
An ActiveX control is an object that supports a customizable programmatic interface. Using the methods, events and properties exposed by the control, web developers can automate their web pages to give the functionality which is equivalent to that of a desktop application.

Introducing LINQ – Part 2
In the first part of this series I introduced you to the new language enhancements in C# 3.0, in this part we will look at querying relational data.

C# 3.0: An Introduction
In this article we will look at some of the language enhancements in C# 3.0. Throughout the article we will use code examples to demonstrate these new enhancements and how to apply them to real world problems. This article will give you the core understanding you will require to further explore the C# 3.0 language using many of its new features.

Top
 
 
 

Discussion


Subject Author Date
placeholder Balanced analysis Keith Fieldhammer 3 days ago

Please login to rate or to leave a comment.

Product Spotlight