When doing Domain Driven Development (DDD) people have tried to make Linq To SQL work as the Data Layer. I have seen a few implementations of this that were not very clean and made more work for the developer. A common solution I’ve seen has been to use the LINQ generated Entities from the dbml file and “convert” them into the corresponding Domain Entity. In this post I will show you how to manually write your Linq to SQL classes to work with your existing Domain Model to avoid such conversions.
Now while you cannot get "total” persistence ignorance with Linq To SQL, it is not as tightly coupled as others seem to think it is. For those who learn by code, check out the download link at the bottom of this page.
The Database
For this post I am using a simple database with the following structure.

The Application
I set up my solution to have 4 projects (C#).
- DomainLinqToSql.Core
- DomainLinqToSql.Data
- DomainLinqToSql.Business
- DomainLinqToSql.Ui
Since this post is geared specifically towards the use of Linq To SQL in an NTier architecture were only really concerned with the Core and Data projects.
Our Entities
I created my entities like I would with any other project.

Though it is not clear from the picture. I am using List<T> and T for my reference types where Linq to SQL would typically use EntitySet<T> and EntityRef<T>. Also you will notice that I am not Implementing from INotifyPropertyChanging and INotifyPropertyChanged contained in the System.ComponentModel namespace. Here’s the secret… you don’t have to!
Some Things to Note
1) You will notice that my EntityBase does not contain anything in it. You may be wondering why I do not just promote my ID fields to the Base class. Well, the answer is Linq To SQL wont let you.
Seriously, you get the following error: “The column or association 'ID' in the mapping had no corresponding member in type 'Store'. Mapping members from above root type is not supported.” I did say it wasn’t perfect.
2) In my Product class in addition to my Store Property I also needed the ID for that store.
3) This is the most important to keep in mind when mapping objects this way. You do lose some of the change tracking and deferred execution abilities of Linq To SQL. But I have not seen anyone implement a better way while still maintaining deferred execution and object tracking.
Our Mappings
So now we have our context and our entities, but we still have not mapped our entities to our database. For that we’re going to create a new XML file and write our mappings (this is something that creating a DBML does for you automatically). Here is the relevant section for my Store Class
<Table Name="dbo.Stores" Member="Stores">
<Type Name="Store">
<Column Name="ID" Member="ID" Storage="_ID" DbType="Int NOT NULL IDENTITY" IsPrimaryKey="true" IsDbGenerated="true" AutoSync="OnInsert" UpdateCheck="Never" />
<Column Name="Name" Member="Name" Storage="_Name" DbType="VarChar(100) NOT NULL" CanBeNull="false" UpdateCheck="Never" />
<Column Name="Description" Member="Description" Storage="_Description" DbType="VarChar(MAX)" UpdateCheck="Never" />
<Association Name="Store_Product" Member="Products" Storage="_Products" ThisKey="ID" OtherKey="StoreID" />
</Type>
</Table>
This snippet is pretty self-explanatory. You can see all of the schema definitions at http://msdn.microsoft.com/en-us/library/bb386907.aspx
The Data Context
So now we need a data context to do all the work against the database. In my data layer I created a new class called AppDataContext that implemented DataContext (in the System.Data.Linq namespace). I created a constructor that took in a connection string and another that took in a connection string and a MappingSource (in the System.Data.Linq.Mapping namespace). The mapping class allows you to load XML files to define your Linq to SQL mappings which we will look at next.
public AppDataContext(string connection) :
base(connection, mapping)
{
}
public AppDataContext(string connection, MappingSource mappingSource) :
base(connection, mappingSource)
{
}
You will notice on line 2 that I am passing a mapping object as our default mapping. This object is set as shown:
private static readonly MappingSource mapping =
XmlMappingSource.FromStream
(Assembly.GetExecutingAssembly()
.GetManifestResourceStream("DomainLinqToSql.Data.AppData.map.xml"));
First, on line 2 we are calling the XmlMappingSource.FromStream method that takes in any stream containing XML for your mapping source.
Line 3 is where I do a little bit of trickery, Since I do not always know where my data layer will be deployed, I use a little bit of .NET Reflection to get the XML file. To accomplish this you must make sure that in the Properties Dialog for the XML File you have Build Action set to Embedded Resource.

The way GetManifestResourceStream works you need to append the file name to the PROJECT NAME (NOT the namespace) for .NET to be able to find the file and read it. [If you have a better way to do this, please let me know in the comments]
The last thing we need to do in our Data Context class is to tell our code about our Entities to have strong typing and intellisence. We do this with a few simple getters.
public Table<Product> Products
{
get
{
return GetTable<Product>();
}
}
public Table<Store> Stores
{
get
{
return GetTable<Store>();
}
}
Finally
Now we have our DataContext, our Mappings, and our Entities. We can now go to our business layer and write code like this.
public Store Read(int key)
{
using (AppDataContext db = new AppDataContext(ConfigurationManager.ConnectionStrings["AppData"].ConnectionString))
{
return db.Stores.FirstOrDefault(x => x.ID == key);
}
}
public List<Store> ReadAll()
{
using (AppDataContext db = new AppDataContext(ConfigurationManager.ConnectionStrings["AppData"].ConnectionString))
{
return db.Stores.ToList();
}
}
At the bottom of this post, I have included a download link to a partially implemented solution with a working user interface written in ASP.NET MVC 2.
Note:
In the downloadable solution I have two implementations of the entity classes. One as I described in this post to demonstrate that you do not have to implement INotifyPropertyChanging and INotifyPropertyChanged and the other ones that do implement these interfaces – to allow more flexibility.
To toggle between using the different types of Entities:
Open the Entities’ .cs file and comment (or uncomment) the preprocessor definition on line 1 of each of the two files.
Downloads
DomainLinqToSql_VS2010.zip (535.99 kb)
VS2008 Solution Comming Soon
LINQ, SQL Server, .NET 4.0
linq, ntier, domain model, domain driven development, data access