Периодические ошибки "The underlying provider failed on Open" при использовании EF4 (edmx model)

Надеюсь, кто-нибудь сможет помочь мне с решением следующей ошибки. Приложение, в котором происходит ошибка, работает в производстве, и я никогда не сталкиваюсь с этой ошибкой сам. Однако около 20 раз в день я получаю сообщение об ошибке, в котором говорится:

The underlying provider failed on Open. ---> System.InvalidOperationException: Соединение не было закрыто. текущее состояние соединения - соединение.

Вот трассировка стека

System.Data.EntityException: Базовый провайдер потерпел неудачу на Open. ---> System.InvalidOperationException: Соединение не было закрыто. Текущее состояние соединения - соединение. at System.Data.ProviderBase.DbConnectionBusy.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) at System.Data.SqlClient.SqlConnection.Open() at HibernatingRhinos.Profiler.Appender.ProfiledDataAccess.ProfiledConnection.Open() at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure) --- Конец внутреннего исключения трассировка стека --- в System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure) в System.Data.EntityClient.EntityConnection.Open() at System.Data.Objects.ObjectContext.EnsureConnection() at System.Data.Objects.ObjectQuery1.GetResults(Nullable1 forMergeOption) at System.Data.Objects.ObjectQuery1.System.Collections.Generic.IEnumerable.GetEnumerator() at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable1 источник) в System.Data.Objects.ELinq.ObjectQueryProvider.b__1[TResult](IEnumerable1 последовательность) в System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable1 query, Expression queryRoot) at System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[S](Expression выражение) в System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
at GuideSites.DomainModel.Repositories.ClinicTermRepository.GetClinicTermByGuideSiteId(Int32 guideSiteId) in C:\Projects\GuideSites\GuideSites.DomainModel\Repositories\ClinicTermRepository.cs:line 20 at GuideSites.Web.Frontend.Helpers.VerifyUrlHelper.RedirectOldUrls() in C:\Projects\GuideSites\GuideSites.Web.Frontend\Helpers\VerifyUrlHelper.cs:line 91 в GuideSites.Web.Frontend.MvcApplication.Application_BeginRequest(Object sender, EventArgs e) в C:\Projects\GuideSites\GuideSites.Web.Frontend\Global.asax.cs:line 412 at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Я использую EF4 через модель EDMX, и я подключаюсь к базе данных (MS SQL 2008) через объектный контекст на основе HttpContext на каждый запрос, чтобы соединения с базой данных не открывались и не закрывались для каждой отдельной части данных, которые мне нужны на данной загрузке страниц.

Мой класс контекста базы данных выглядит так:

public class DatabaseContext : IDisposable
{
    private const string ContextName = "context";
    private static dbEntities _dbEntities;

    public dbEntities GetDatabaseContext()
    {
        SqlConnection.ClearAllPools();

        if (HttpContext.Current == null)
            return _dbEntities ?? (_dbEntities = new dbEntities());

        if (HttpContext.Current.Items[ContextName] == null)
            HttpContext.Current.Items[ContextName] = new dbEntities();

        _dbEntities = (dbEntities)HttpContext.Current.Items[ContextName];
        if (_dbEntities.Connection.State == ConnectionState.Closed)
        {
            _dbEntities.Connection.Open();
            return _dbEntities;
        }

        return _dbEntities;
    }


    public void RemoveContext()
    {
        if (HttpContext.Current != null && HttpContext.Current.Items[ContextName] != null)
        {
            ((dbEntities)HttpContext.Current.Items[ContextName]).Dispose();
            HttpContext.Current.Items[ContextName] = null;
        }

        if (_dbEntities != null)
        {
            _dbEntities.Dispose();
            _dbEntities = null;
        }
    }


    public void Dispose()
    {
        RemoveContext();
    }

}

В моих репозиториях я использую контекст базы данных так:

public class SomeRepository
{
    private static readonly object Lock = new object();
    private readonly dbEntities _dbEntities;

    public SomeRepository()
    {
        var databaseContext = new DatabaseContext();
        _dbEntities = databaseContext.GetDatabaseContext();
    }


    public IEnumerable<SomeRecord> GetSomeData(int id)
    {
        lock (Lock)
        {
            return
                _dbEntities.SomeData.Where(c => c.Id == id);
        }
    }
 }

Я читал о том, что блокировка (Lock) должна помочь в решении этой проблемы, но в моем случае это не помогло. И вообще было трудно найти темы, описывающие именно мою проблему, не говоря уже о решении проблемы.

Приложение - это приложение ASP.NET MVC3, и оно настроено как одно приложение, работающее для 9 различных веб-сайтов (домен определяет содержимое, которое будет обслуживаться клиентом). На 9 сайтах ежедневно просматривается не более 2.000 страниц, поэтому база данных не должна быть нагружена.

Надеюсь, кто-нибудь сможет помочь, и, пожалуйста, дайте мне знать, если я что-то забыл упомянуть.

13
задан hylle 30 January 2012 в 19:17
поделиться