C# – Problem using LINQ to SQL with one DataContext per atomic action

c++ddd-repositorieslinq-to-sqlpersistence

I have started using Linq to SQL in a (bit DDD like) system which looks (overly simplified) like this:

public class SomeEntity // Imagine this is a fully mapped linq2sql class.
{
    public Guid SomeEntityId { get; set; }
    public AnotherEntity Relation { get; set; }
}

public class AnotherEntity // Imagine this is a fully mapped linq2sql class.
{
    public Guid AnotherEntityId { get; set; }
}

public interface IRepository<TId, TEntity>
{
    Entity Get(TId id);
}

public class SomeEntityRepository : IRepository<Guid, SomeEntity>
{
    public SomeEntity Get(Guid id)
    {
        SomeEntity someEntity = null;
        using (DataContext context = new DataContext())
        {
            someEntity = (
                from e in context.SomeEntity
                where e.SomeEntityId == id
                select e).SingleOrDefault<SomeEntity>();
        }

        return someEntity;
    }
}

Now, I got a problem. When I try to use SomeEntityRepository like this

public static class Program
{
    public static void Main(string[] args)
    {
        IRepository<Guid, SomeEntity> someEntityRepository = new SomeEntityRepository();
        SomeEntity someEntity = someEntityRepository.Get(new Guid("98011F24-6A3D-4f42-8567-4BEF07117F59"));
        Console.WriteLine(someEntity.SomeEntityId);
        Console.WriteLine(someEntity.Relation.AnotherEntityId);
    }
 }

everything works nicely until the program gets to the last WriteLine, because it throws an ObjectDisposedException, because the DataContext does not exist any more.

I do see the actual problem, but how do I solve this? I guess there are several solutions, but none of those I have thought of to date would be good in my situation.

  • Get away from the repository pattern and using a new DataContext for each atomic part of work.
    • I really would not want to do this. A reason is that I do not want to be the applications to be aware of the repository. Another one is that I do not think making linq2sql stuff COM visible would be good.
    • Also, I think that doing context.SubmitChanges() would probably commit much more than I intended to.
  • Specifying DataLoadOptions to fetch related elements.
    • As I want my Business Logic Layer to just reply with some entities in some cases, I do not know which sub-properties they need to use.
  • Disabling lazy loading/delayed loading for all properties.
    • Not an option, because there are quite a few tables and they are heavily linked. This could cause a lot of unnecessary traffic and database load.
  • Some post on the internet said that using .Single() should help.
    • Apparently it does not …

Is there any way to solve this misery?

BTW: We decided to use Linq t0 SQL because it is a relatively lightweight ORM solution and included with the .NET framework and Visual Studio. If the .NET Entity Framework would fit better in this pattern, it may be an option to switch to it. (We are not that far in the implementation, yet.)

Best Solution

Rick Strahl has a nice article about DataContext lifecycle management here: http://www.west-wind.com/weblog/posts/246222.aspx.

Basically, the atomic action approach is nice in theory but you're going to need to keep your DataContext around to be able to track changes (and fetch children) in your data objects.

See also: Multiple/single instance of Linq to SQL DataContext and LINQ to SQL - where does your DataContext live?.

Related Question