Linq To SQL : LinqContext per Unit of Work

11 11 2008

To implement a Linq To SQL Oriented solution, there are many ways to construct your application. But only one interested me : the Context per Unit of Work Architecture.

When using Linq To SQL, you need to instanciate a Context which contains your entities tables and allow you to apply query methods. But when your application is construct with many layers, you only can pass Context through methods to keep the same context during your business operations. It is the same problem when a transaction is required(managed by Linq To SQL Context though optimistic transaction).

When using the Unit of Work architecture proposed by Microsoft and few developpers, most of the common operation is easier. Then, I’ll explain the main idea :

I’ll suppose that we have a 2 layers application, called Web & BLL(contains DAL through Linq To SQL Schema).

We want to :

  • Work with a unique Linq To SQL Context during a HTTP Request(so only one per user request)
  • Access to the Context in Web layer(indirectly) and BLL layer(directly)
  • Denied access to the Context in code-behind

The first step is to create a controller class in the BLL layer to access to the context.

public class MyDataContext

{

public static IDataContextStorage MyDataContextStorage;

public static LinqContext Current

{

get

{

return MyDataContextStorage.Current;

}

set

{

MyDataContextStorage.Current = value;

}

}

public static void Save()

{

Current.SubmitChanges();

}

}

And create the following interface:

public interface IDataContextStorage

{

LinqContext Current { get; set; }

}

Now, we have a controller which can be called by the Web and BLL Layer. Accessing from web is not a good practice, so we can change to internal if we want to restrict access to BLL only and set the Current Property type return to object. However, I don’t like to cast each time I need my context, so a leave it like that.

MyDataContext is the wrapper to access to the Context. but we now need to store your context during your HTTP Request. We need to create the following class that allow us to store the context and access it for each user :

public class HttpDataContextStorage:IDataContextStorage

{

public MyBLL.LinqContext Current

{

get {

if ((MyBLL.LinqContext)HttpContext.Current.Items["DataContext"] == null)

HttpContext.Current.Items["DataContext"] = new MyBLL.LinqContext();

return (MyBLL.LinqContext)HttpContext.Current.Items["DataContext"]; }

set { HttpContext.Current.Items["DataContext"] = value; }

}

}

This class need to be placed in App_Code in Web layer(there are some HttpContext reference, so…).

For each application request, we are going to create a Context and destroy it when request is finished. Write in your global.asax.cs:

void Application_BeginRequest(object sender, EventArgs e)

{

MyDataContext.MyDataContextStorage = new HttpDataContextStorage();

}

void Application_EndRequest(object sender, EventArgs e)

{

MyDataContext.Current.Dispose();

}

Ok, all is defined.

when we need to execute a Linq to SQL Query, we only need to write :

MyDataContext.Current.Users.Where(u=>u.Id==1);

“Users” is a entity table for this sample.

When saving is required, do: MyDataContext.Save() or MyDataContext.Current.SubmitChanges()

With this strucutre, Linq Context is always available when you need it and allow to perform transaction through many methods calling.

However, some issues are known, as :

  • Serialization : If you do a full loading of Context, binding with associated object can provoke a serialization failure.
  • It is a HTTP Unit of work concept. If you want to perform asynchronous tasks, the Context will not be available. So keep in mind to build your MyDataContext Controller with features that allow custom Context loading.

This Linq To SQL Context Architecture is a simple sample to show the main idea. Sure, It can be improved to restrict the layers access, check if we use the HTTP Linq Context or a New Context for asynchronous tasks…

Reminder: A Linq Overview Ticket is available here to see others architectures and statistics.





Linq To Entity/Entity Framework with SP1

22 10 2008

When the Linq word begin to spread to the developper’s world, I immediatly inform me about what is it and what can I do with “that”. After trying Linq To Object, Linq To XML, Linq To SQL and Linq To Entity, I was convinced that it was the right path to follow. But for Data management, I was preferring Linq To SQL because Linq To Entity utilisation was boring(Stored Procedure to write).
After SP1, Linq To Entity was not the same. So I studied it more deeper… And some good things falls.

If I must define what Linq To Entity can bring you compared to Linq To SQL, I will say:

  • Inheritance
  • Complex types
  • Define a view like a table(CRUD actions with stored procedures)

The real purpose of Linq To Entity is to define an object conception that will not necessary match to your database shema relationship. A real good thing when implementing your business layer and rules.

In this example, the class UserDB is a copy of the User Table(with Linq To SQL or others code generation tools).

With linq to Entity, we can build your object model with inheritances and rules(User is defined as abstract). So we cannot used a user directly but we need to use the child classes(not abstract). The mapping to get an administrator user is done by the model by auto-filling the required filters. Magic…

I invite the Linq To SQL users to gather more information about Linq To Entity and see the added functionnalities.





Linq To SQL Generic Controller

20 10 2008

With the power of Linq language, it’s easy to use Linq To SQL to build 95% of the data access interrogation.

But you will notify that 2/3 of your data access methods is always the same, as GetById, GetAll, Insert, DeleteById…

So Microsoft staff has written a class named GenericController that allow you to centralize all standard methods in one class. You only need to inherit from it and a good part of your job is done.

http://code.msdn.microsoft.com/multitierlinqtosql

If you look more deeper in this pack, you will find some other classes written to instanciate one LinqContext by Query or a Linq To SQL Debugger(see also my ticket on DebugWriter).





Linq Overview

23 09 2008

During my migration from .NET 2.0 to .NET 3.0/3.5, my first tought was : ‘With .NET 3.5, I can used Linq To SQL and stop to bore me with all the code generation tools”. I don’t want to crush the glory of tools like Raptier or Code Smith, but an ORM produce by Microsoft can be better in generation time(class generation and integration) and simplicity. It was true(for common uses). But better than that. Linq offers many others functionalities(strongly typed, composite queries, relashionship between objects and many more). And I began to forget all about others problems when the Graal was not here…

After a month of research, I have started to write a document on my Linq feedback and I share it today :-)

linq