Entity Framework not saving data to database on context.SaveAsync() while using Autofac

Hi,

Recently I was using Entity Framework with a DB first approach in an application and using the Repository pattern with Unit of Work to have easy management of DB operations.

So my repository constructor accepted an IDataContext object (IDataContext is a custom interface I had written which encapsulates the DbContext generated after adding Entity Data model. Refer sample code below.

RepositoryBase:

public class RepositoryBase<TEntity> : IRepositoryBase<TEntity>
where TEntity : class

{

        public RepositoryBase(IDataContext context)

        {

        }

}

The UnitOfWork class had a constructor that accepted the ILifetimeScope object and using this object, I was resolving the context in the constructor. I also had a couple of repositories specified as properties in this class. Refer sample code below.

UnitOfWork.cs

public class UnitOfWork : IUnitOfWork

{

    public UnitOfWork(ILifetimeScope scope)

    {
        this.scope = scope.
        this.Context = this.scope.Resolve<IDataContext>();

    }

    public Task<int> SaveAsync()

    {

        return this.Context.SaveAsync();

    }

   // Repositories

    public IRepositoryBase<SampleClass> SampleRepository

    {

        get
        {
            if(this.sampleClassRepository == null) this.sampleClassRepository = this.scope.Resolve<IRespositoryBase<SampleClass>>();    // Observe above line later
             return this.sampleClassRepository;
        }

    }

}

The code that was using this repository was something like

using(var uow = this.scope.Resolve<IUnitOfWork>())
{

    uow.SampleRepository.Insert(newEntity);
    uow.SaveAsync();    // This should actually save above new entity into DB but it wasn't saving anything.
}

The problem with this approach was that When I was working with the repository, Autofac initially sees that the repository object has not been created and so creates a new object by resolution by injecting a NEW CONTEXT object as it sees that repository constructor requires an IDataContext object.

So because of this issue, we end up with 2 different contexts, one which just got created while trying to access the repository and this also has the change (insert), and the other which got created while creation of UnitOfWork object. And what happens is insert action goes into repository context object and Save action works upon the UnitOfWork’s context object. Hence, nothing fails but nothing happens in DB as well.

To make sure that repositories are also using the same context as UnitOfWork, what we can do is to pass the unitOfWork’s context to the Resolve method of ILifetimeScope as shown below.

if(this.sampleClassRepository == null) 
    this.sampleClassRepository = 
    this.scope.Resolve<IRespositoryBase<SampleClass>>
        (new TypedParameter(typeof(IDataContext), this.Context));

This is present in the UnitOfWork class. And this.Context refers to unitOfWork’s context. This statement ensures that when repository instance is being created, instead of creating a new context, we’re going to reuse the context of unitOfWork and so any Save operations performed would thus perform the operations on the database as well.

Hope this helps!

Reference : http://docs.autofac.org/en/latest/resolve/parameters.html

Advertisements

About Amogh Natu

Technology enthusiast, Associate Consultant @ Microsoft, music lover, love my guitar, Microsoft.NET, ASP.NET, C#.NET Professional.
This entry was posted in .NET, General and tagged , , , , , , , . Bookmark the permalink.

Your comments or opinions.....

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s