实体框架缓慢关闭连接

时间:2015-02-18 21:36:31

标签: sql-server asp.net-mvc entity-framework database-connection c#-5.0

我正在构建一个MVC 5 Web应用程序,我正在使用实体框架6,我有MS SQL Server 2008 R2作为我的数据库。我使用连接池来确保尽可能快地获得数据库操作的连接。我在Web.config中的连接字符串如下

<add name="MyConnectionPoolConnectionString" connectionString="Data Source=MyHOST;Initial Catalog=TEST_DB;User Id=sa;Password=password1; Min Pool Size=10;MultipleActiveResultSets=True;" providerName="System.Data.SqlClient" />

我注意到从连接池获得连接非常快,即几十到几百毫秒

但是,我还注意到关闭连接(在连接池中意味着连接返回到池)需要相当长的时间(即平均在2000ms和5000ms之间(2 - 5秒)) )。

以下是我的分析日志的摘录

打开连接所需的时间

2015-02-18 21:06:55,497 Opened connection at 18/02/2015 21:06:55 92.65 ms

关闭/返回连接所需的时间

 Closed connection at 18/02/2015 21:07:01 2543.06 ms

请注意,打开连接需要92毫秒,关闭连接需要2500毫秒。 顺便说一句,这些统计数据是我自己的EF框架提供的,即通过在EF上下文中设置数据库道具的Log属性,即

MyTestAppDbContext.Database.Log = Logger.Debug;

我不明白为什么从连接池获取连接速度如此之快,但是EF需要很长时间才能将连接返回到池中(即关闭连接),更重要的是如何加快连接速度发布/关闭连接

这对我来说非常重要,因为Web应用程序需要非常敏感,因为我必须为每个请求创建EF Dbcontext,如果EF为关闭/释放连接增加额外的2-5秒开销,它降低了应用的响应能力。

MyTestAppDbContext.cs

public partial class MyTestAppDbContext : DbContext
{
    public ILogger Logger { get; set; }

    static MyTestAppDbContext()
    {
        System.Data.Entity.Database.SetInitializer<MyTestAppDbContext>(null);
    }

    public MyTestAppDbContext(ILogger logger)
        : base("Name=MyConnectionPoolConnectionString")
    {

            this.Configuration.LazyLoadingEnabled = false; 
            this.Configuration.ProxyCreationEnabled = false;
            Logger = logger;
            this.Database.Log = Logger.Debug;
    }

    public override int SaveChanges()
    {
        Exception entityFrameworkExceptions = null;
        String exMsg = "";
        int result = 0;
        try
        {

            if (this.ChangeTracker.HasChanges())
            {
                // Get all Added/Deleted/Modified entities (not Unmodified or Detached)
                foreach (var ent in this.ChangeTracker.Entries().Where(p => p.State == EntityState.Added || p.State == EntityState.Deleted || p.State == EntityState.Modified))
                {

                    // For each changed record, log the activity performed
                   Logger.Debug("Detected Changes");
                }

                result = base.SaveChanges();
            }
        }
        catch (DbEntityValidationException dbEx)
        {
            entityFrameworkExceptions = dbEx;
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {
                    //System.Diagnostics.Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
                    exMsg += String.Format("\nProperty: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
                    Logger.Debug(String.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage));
                }
            }
        }
        catch (DbUpdateException dbEx)
        {
            entityFrameworkExceptions = dbEx;
            Logger.Debug(String.Format("Exception Message: {0}", dbEx.Message));
            Logger.Debug(String.Format("InnerException: {0}", dbEx.InnerException));
            Logger.Debug(String.Format("StackTrace: {0}", dbEx.StackTrace));
            Logger.Debug(String.Format("Call Stack: {0}", CommonUtils.GetCallStackAsString()));
        }

        catch (Exception ex)
        {
            entityFrameworkExceptions = ex;
            Logger.Debug(String.Format("Exception Message: {0}", ex.Message));
            Logger.Debug(String.Format("InnerException: {0}", ex.InnerException));
            Logger.Debug(String.Format("StackTrace: {0}", ex.StackTrace));
            Logger.Debug(String.Format("Call Stack: {0}", CommonUtils.GetCallStackAsString()));
        }
        if (entityFrameworkExceptions != null)
        {
            exMsg = exMsg + "\n" + entityFrameworkExceptions.Message + @"\n" + entityFrameworkExceptions.StackTrace + @"\n" + entityFrameworkExceptions.InnerException;
            entityFrameworkExceptions = new HttpException(500, @"Exception applying changes in PaceDBContext (i.e. Entity Framework)\n" + exMsg+"\n"+CommonUtils.GetCallStackAsString());

            throw entityFrameworkExceptions;

        }
        return result;
    }
}

IUnitOfWork.cs

public interface IUnitOfWork /*: IDisposable*/
{
   MyTestAppDbContext MyTestAppDbContext { get; set; }
   Exception Save();
}

UnitOfWork.cs

public class UnitOfWork :  IUnitOfWork, IDisposable
{
    private bool disposed = false;

    public MyTestAppDbContext MyTestAppDbContext {get; set;}
    public ILogger Logger { get; set; }

    public Exception Save()
    {
        Exception entityFrameworkExceptions = null;
        String exMsg = "";//, callStackAsString = "";
        try
        {
            System.Diagnostics.Trace.TraceInformation("Saving Db Changes in UnitOfWork");
            MyTestAppDbContext.SaveChanges();
            System.Diagnostics.Trace.TraceInformation("Finished saving Db Changes in UnitOfWork");
        }
        catch (DbEntityValidationException dbEx)
        {
            entityFrameworkExceptions = dbEx;
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {

                    exMsg += String.Format("\nProperty: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
                    Logger.Debug(String.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage));
                }
            }
        }
        catch (DbUpdateException dbEx)
        {
            entityFrameworkExceptions = dbEx;
            this.LogException(dbEx);
        }

        catch (Exception ex)
        {
            entityFrameworkExceptions = ex;
            this.LogException(ex);
        }
        if (entityFrameworkExceptions != null)
        {
            exMsg = "\n" + entityFrameworkExceptions.Message + @"\n" + entityFrameworkExceptions.StackTrace + @"\n" + entityFrameworkExceptions.InnerException+"\n"+CommonUtils.GetCallStackAsString();
            entityFrameworkExceptions =  new HttpException(500, @"Exception applying changes in PaceDBContext (i.e. Entity Framework)\n" + exMsg);


            throw entityFrameworkExceptions;

        }

        return entityFrameworkExceptions;
    }

    protected virtual void Dispose(bool disposing)
    {

        this.Save();
        if (!this.disposed)
        {
            if (disposing)
            {

                MyTestAppDbContext.Dispose();
            }
        }
        this.disposed = true;
    }

    public void Dispose()
    {

        Dispose(true);
        GC.SuppressFinalize(this);
    }

    private void LogException(Exception ex){
        Logger.Debug(String.Format("Exception Message: {0}", ex.Message));
        Logger.Debug(String.Format("InnerException: {0}", ex.InnerException));
        Logger.Debug(String.Format("StackTrace: {0}", ex.StackTrace));
    }
}

UserRepository.cs

public class UserRepository : IUserRepository
{

    public IUnitOfWork UnitOfWork { get; private set; }

    public UserRepository(IUnitOfWork unitOfWork)
    {
        this.UnitOfWork = unitOfWork;
    }


    public Users GetUserByUserId(string userId)
    {
        if (!String.IsNullOrEmpty(userId)){
        var user = from u in UnitOfWork.MyTestAppDbContext.Users
                   where u.UserId.Trim().Equals(userId.Trim())
                   select u;
        return user.SingleOrDefault();
        }
        return null;
    }

    public string GetUserFullName(string userId)
    {
        string fullname = null;
        if (!String.IsNullOrEmpty(userId))
        {
            var user = (from u in UnitOfWork.MyTestAppDbContext.Users
                       where u.UserId.Trim().Equals(userId.Trim())
                       select u).SingleOrDefault();
            if (user != null)
            {
                if (!String.IsNullOrEmpty(user.FirstName))
                    fullname += user.FirstName + " ";
                if (!String.IsNullOrEmpty(user.LastName))
                    fullname += user.LastName;

            }
        }
        return fullname;
    }

    public long GetUserGroupId(string userId)
    {
        if (!String.IsNullOrEmpty(userId))
        {
            var user = (from u in UnitOfWork.MyTestAppDbContext.Users
                       where u.UserId.Trim().Equals(userId.Trim())
                       select u).SingleOrDefault();
            if (user != null)
                return user.UserGroupId;
        }
        return -1;
    }
}

由于

0 个答案:

没有答案