1

I'm currently developing an ASP.NET MVC application using the latest Entity Framework version and I do have some strange behaviour.

I share my context through the different repositories, so that way I can call a SaveChanges anywhere in the project, and all the changes over all my repositories are being changed.

public UnitOfWork(IDbContext context)
    : base(context)
{
    versioningRepository = new Repository<Versioning>(context, this);

    settingRepository = new Repository<Setting>(context, this);
    siteRepository = new VersionedRepository<Site, int>(context, this);
    pageRepository = new VersionedRepository<Page, int>(context, this);
    layoutRepository = new VersionedRepository<Layout, int>(context, this);
    assemblyRepository = new VersionedRepository<Assembly, int>(context, this);
    logRepository = new Repository<Log>(context, this);
}

Now, when I'm starting the application and I fire up multiple tabs requesting the same page at the same time then the following error might popup:

An exception of type 'System.Data.Entity.Core.EntityException' occurred in EntityFramework.SqlServer.dll but was not handled in user code

Additional information: The underlying provider failed on Open.

The inner exception is:

The connection was not closed. The connection's current state is open.

The connection state might eventually change to 'Closed', 'Connecting'. As soon as the application is running and I refresh various pages, the same error does not show anymore, so can anyone tell me whe I'm having this behaviour?

Also, the following line can give me a 'NullReferenceException' and also I don't have a clue why this is happening:

return !query.Any() ? null : !query.Where(filter).Any() ? null : query.First(filter);

After a refresh, I don't get the 'NullReferenceException' neither.

Important to know that I'm using Unity to instantiate my DbContext and my UnitOfWork.

container.RegisterType<IDbContext, OxygenDataContext>();
container.RegisterType<IUnitOfWork, UnitOfWork>(new PerRequestLifetimeManager());

The IUnitOfWork interface does implement the IDisposable interface. This is implemented like:

protected virtual void Dispose(bool disposing)
{
    if (disposing) { Context = null; }
}

public void Dispose()
{
    Dispose(true);
}

Thanks for the help.

Community
  • 1
  • 1
Complexity
  • 5,682
  • 6
  • 41
  • 84
  • Does your repositories are also registered using PerRequestLifetimemanager()? Consider using lifetime limited to PerThread maybe (it's a shot, maybe helps). – Fka Sep 24 '14 at 09:31
  • Using a PerThreadLifetimeManager does not resolve the issue. Also, how should I instantiate my repositories through the PerRequest since they are not constructed using Unity. Unity does construct the unit of work on a per request basis and the unit of work is constructing my repositories, so I believe they are correctly registered. – Complexity Sep 24 '14 at 09:33
  • Something to consider: "Although the PerRequestLifetimeManager class works correctly and can help you to work with stateful or thread-unsafe dependencies within the scope of an HTTP request, it is generally not a good idea to use it if you can avoid it. Using this lifetime manager can lead to bad practices or hard to find bugs in the end user’s application code when used incorrectly." – Paul Zahra Sep 24 '14 at 10:22
  • and "The dependencies you register with the Unity container should be stateless, and if you have a requirement to share common state between several objects during the lifetime of an HTTP request, then you can have a stateless service that explicitly stores and retrieves this state using the System.Web.HttpContext.Items collection of the System.Web.HttpContext.Current object." – Paul Zahra Sep 24 '14 at 10:22
  • Ok, I'm a bit lost right now. – Complexity Sep 24 '14 at 10:40
  • Why is your context defined with transient life time and your unit of work per request? – L-Four Sep 24 '14 at 11:13
  • If I make them both with a per request lifetime, the exact same error keeps popping up. What's wrong that my context is a transient lifetime if I may ask? – Complexity Sep 24 '14 at 11:15
  • Potentially the problem is that you are using the default TransientLifetimeManager which does nothing but ensure that instances are created new everytime... e.g. If you want the container to create or return a singleton instance of a type when you call the Resolve method, you can use the ContainerControlledLifetimeManager – Paul Zahra Sep 24 '14 at 11:20
  • Try PerThreadLifetimeManager – L-Four Sep 24 '14 at 11:24
  • I wonder if it's something to do with the way EF is enlisting queries in it's transactions in a multi-threaded environment, can you try managing them more tightly? Have a read of this http://stackoverflow.com/questions/5942930/entity-framework-transaction-with-multiple-threads – Paul Zahra Sep 24 '14 at 11:30
  • If I understand this correctly, this is another issue. In here, I do have the problem that the connection is already opened. – Complexity Sep 24 '14 at 13:15
  • For your null reference exception issue, that code would be simpler and more efficient if you used query.FirstOrDefaultAsync(filter). In general, you should be using the async versions of these methods when possible Not 100% what the issue is to give you the null reference exception, but it wouldn't matter if you use the appropriate method above. – ChoptimusPrime Sep 24 '14 at 15:01

1 Answers1

1

Actually if you are planning to work with the Martin Fowler patterns you are implementing them in the wrong way.

  1. First the sole purpose of a Unit of Work is to aggregate transactional operation for write/update and delete into one logical component
  2. Second, a Unit of Work should not provide any knowledge or capabilities of read, you are breaking one of the SOLID principle here, the SOC (Separation of Concerns)
  3. Third, you are working with an ORM and this is your Repository. You can abstract from the ORM by using CQRS, OData or a Query pattern but having so many abstract repositories does not make sense at all
  4. Finally, if you plan to work with the Inversion of Control pattern then also your repository should be injected. Why? Because they are abstract dependencies

For a Unit of Work

public Interface IUnitOfWork
{
   void StartTransaction();
   void Commit();
   void Rollback();
   void Save<T>(T entity);
   void Delete<T>(T entity);
}

public Interface IRepository
{
   IQueryable<T> Get<T>();
   SingleResult<T> GetSingle<T, TKey>(TKey key);
}
Raffaeu
  • 6,694
  • 13
  • 68
  • 110
  • Thanks for the answer, but it sounds a bit abstract to me. Do you mind providing me with an example about the generic idea? – Complexity Sep 24 '14 at 09:40
  • This does not completely answer my question. In the first place, I want to know why I'm having this behaviour and why I do have the 'NullReferenceException' in the first place. – Complexity Sep 24 '14 at 09:49
  • First of all I kindly suggestion to read this: http://martinfowler.com/eaaCatalog/unitOfWork.html and this http://martinfowler.com/eaaCatalog/repository.html and move forward – Raffaeu Sep 24 '14 at 11:11