views:

24

answers:

1

I have an ASP MVC application using LINQ to SQL for data access. I am trying to use the Repository and Unit of Work patterns, with a service layer consuming the repositories and unit of work. I am experiencing a problem when attempting to perform updates on a particular repository.

My application architecture is as follows:

My service class:

public class MyService
{
   private IRepositoryA _RepositoryA;
   private IRepositoryB _RepositoryB;
   private IUnitOfWork _unitOfWork;

   public MyService(IRepositoryA ARepositoryA, IRepositoryB ARepositoryB, IUnitOfWork AUnitOfWork)
   {
      _unitOfWork = AUnitOfWork;
      _RepositoryA = ARepositoryA;
      _RepositoryB = ARepositoryB;
   }

   public PerformActionOnObject(Guid AID)
   {
      MyObject obj = _RepositoryA.GetRecords()
                                 .WithID(AID);
      obj.SomeProperty = "Changed to new value";
      _RepositoryA.UpdateRecord(obj);  
      _unitOfWork.Save();
   }
}

Repository interface:

public interface IRepositoryA
{ 
   IQueryable<MyObject> GetRecords();
   UpdateRecord(MyObject obj);
}

Repository LINQtoSQL implementation:

public class LINQtoSQLRepositoryA : IRepositoryA
{
    private MyDataContext _DBContext;

    public LINQtoSQLRepositoryA(IUnitOfWork AUnitOfWork)        
    {
        _DBConext = AUnitOfWork as MyDataContext;           
    }

    public IQueryable<MyObject> GetRecords()
    {             
        return from records in _DBContext.MyTable                   
               select new MyObject
               {
                  ID = records.ID,
                  SomeProperty = records.SomeProperty
               }
    }


    public bool UpdateRecord(MyObject AObj)
    {
        MyTableRecord record = (from u in _DB.MyTable
                    where u.ID == AObj.ID
                    select u).SingleOrDefault();

        if (record == null)
        {
            return false;
        }           

        record.SomeProperty = AObj.SomePropery;
        return true;
    }
 }

Unit of work interface:

public interface IUnitOfWork
{  
    void Save();
}

Unit of work implemented in data context extension.

public partial class MyDataContext : DataContext, IUnitOfWork
{
   public void Save()
   {
      SubmitChanges();
   }
}

StructureMap registry:

 public class DataServiceRegistry : Registry
    {
        public DataServiceRegistry()
        {            
            // Unit of work
            For<IUnitOfWork>()               
                .HttpContextScoped()                
                .TheDefault.Is.ConstructedBy(() => new MyDataContext());

            // RepositoryA
            For<IRepositoryA>()
                .Singleton()
                .Use<LINQtoSQLRepositoryA>();    

            // RepositoryB
            For<IRepositoryB>()
                .Singleton()
                .Use<LINQtoSQLRepositoryB>();    
         }
     }

My problem is that when I call PerformActionOnObject on my service object, the update never fires any SQL. I think this is because the datacontext in the UnitofWork object is different to the one in RepositoryA where the data is changed. So when the service calls Save() on it's IUnitOfWork, the underlying datacontext does not have any updated data so no update SQL is fired.

Is there something I've done wrong in the StrutureMap registry setup? Or is there a more fundamental problem with the design?

Many thanks.

A: 

It's generally not a good idea to have something registered as singleton if it has scoped dependencies. Most likely they are holding onto old instances of IUnitOfWork, like you said.

Any particular reason your repositories are singleton? I would suggest making them HttpContext scoped as well, that way they will be in sync.

Robin Clowers