none
(DbContext as IObjectContextAdapter).ObjectContext.Conncection.Close() is not working in EF6. RRS feed

  • Question

  • Hi,

    I am using Entity Framework 6.1.3 in my Web API service with code first approach.

    I had custom Message handler for API. From message handler for every request i opens db connection by invoking MyContext.Open() and closes the db connection by invoking MyContext.Close().

    After 2 days running continously(i.e this Web API service is accesed by client for every 3 seconds.) i get time out execption with coonection pool error.

    When I check log it show db connection is closed. I dont know why i am getting this error.

    ------------------------------------------------------------------------------------------------------------------------

    Below is the error log: 

    System.Data.Entity.Core.EntityException: The underlying provider failed on Open. ---> System.InvalidOperationException: Timeout expired.  The timeout period elapsed prior to obtaining a connection from the pool.  This may have occurred because all pooled connections were in use and max pool size was reached.

       at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)

       at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)

       at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)

       at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)

       at System.Data.SqlClient.SqlConnection.Open()

       at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext](TTarget target, Action`2 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)

       at System.Data.Entity.Infrastructure.Interception.DbConnectionDispatcher.Open(DbConnection connection, DbInterceptionContext interceptionContext)

       at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.<>c__DisplayClass1.<Execute>b__0()

       at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)

       at System.Data.Entity.Core.EntityClient.EntityConnection.Open()

       --- End of inner exception stack trace ---

       at System.Data.Entity.Core.EntityClient.EntityConnection.Open()

    --------------------------------------------------------------------------------------------------------------------------------------

    Coonection String: 

    <connectionStrings>
        <add name="abc" connectionString="data source=Server1\abc;initial catalog=TestDB;persist security info=True;user id=username;password=XXXX;multipleactiveresultsets=True;application name=EntityFramework" providerName="System.Data.SqlClient" />
      </connectionStrings>

    ----------------------------------------------------------------------------------------------------------------------

    Below is the message handler class code:

      public class MessageHandler : DelegatingHandler, IExceptionHandler
        {
            public MessageHandler()
            {

            }

            protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
            {       
                try
                {
                    MyContext.Open();
                }
                catch (Exception ex)
                {
                    MyContext.Close();
                }          

                try
                {
                    response = await base.SendAsync(request, cancellationToken);
                }
                catch (Exception ex)
                {
                    MyContext.Close();               
                }            
                finally
                {               
                     MyContext.Close();                
                }
    }
    }

    --------------------------------------------------------------------------------------------------------------------------

    Below is MyContext class  code        

    public class MyContext 
        {  
    private static Context instance = null;
    private Context(){}   
    public MyDBContext MyDBContext {get;set;}
         public static MyContext Instance
            {
                get
                {

                    if (instance == null)
                    {
      instance = new MyContext();
      instance.MyDBContext = new MyDBContext();
                       return instance;
                    }

                    return instance;
    }
    }
    public static Open()
    {
     if (instance.MyDBContext != null)
                {

                 if (instance.MyDBContext.ObjectContext.Connection.State != ConnectionState.Open)
                 {
                     instance.MyDBContext.ObjectContext.Connection.Open();
                 }

               }
    }

    public staic Close() 
    {
     if (instance.MyDBContext != null)
                {
                    if (instance.MyDBContext.ObjectContext.Connection.State != ConnectionState.Closed)
                    {
                        instance.MyDBContext.ObjectContext.Connection.Close();
                        Log.Info("DB Connection :" + ConnectionState.Closed.ToString());
                    }

                    instance.MyDBContext.Dispose();
                }
    }
    }

    public class MyDBContext:DBContext

    {

     public ObjectContext ObjectContext
            {
                get { return (this as IObjectContextAdapter).ObjectContext; }
            }

    }

    --------------------------------------------

    Will "instance.MyDBContext.ObjectContext.Connection.Close(); " line of code really closeses the connection? I suspect some problem here.

    Please reply the query. I am in urgent to fix this issue.


    Ravishankar Boyina



    Wednesday, July 6, 2016 2:39 PM

All replies

  • Hi Ravishankar Boyina,

    >> Will "instance.MyDBContext.ObjectContext.Connection.Close(); " line of code really closeses the connection? I suspect some problem here.

    From the following code, it seems that you have not close it if it doesn't throw any exception. please close it after you use it.

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { try { MyContext.Open();

    //you handle logic

    MyContext.Close(); } catch (Exception ex) { MyContext.Close(); }


    In addition, I would suggest that you could use unit of work pattern instead of singleton pattern. and the following link some reasons.

    http://www.britishdeveloper.co.uk/2011/03/dont-use-singleton-datacontexts-entity.html

    For more information about unit of work, please refer to:

    http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

    Note: This response contains a reference to a third party World Wide Web site. Microsoft is providing this information as a convenience to you. 

    Microsoft does not control these sites and has not tested any software or information found on these sites;Therefore, Microsoft cannot make any representations regarding the quality, safety, or suitability of any software or information
    found there.

    There are inherent dangers in the use of any software found on the Internet, and Microsoft cautions you to make sure that you completely understand the risk before retrieving any software from the Internet.

    Best regards,

    Cole Wu


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Thursday, July 7, 2016 3:36 AM
    Moderator
  • Hi Cole Wu,

    Thanks for your reply. But below is my scenario.

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { try { MyContext.Open(); } catch (Exception ex) { MyContext.Close(); } try {

    // before below line of code is invoked i need to open the context. Then only i can

    // connect to database.

    response = await base.SendAsync(request, cancellationToken); } catch (Exception ex) { MyContext.Close(); } finally { MyContext.Close(); } }



    Ravishankar Boyina

    Thursday, July 7, 2016 7:34 PM
  • Hi Ravishankar Boyina,

    According to your code snippet, it seems that you make a log when run Close() method. please check if the log records have related close message. If it have not related close message, could you please provide a simple demo about the issue and related reproduce method. we'll reproduce your issue on our side and try find a solution to resolve it.

    In addition, I would suggest that you could use unit of work instead of singleton.

    Best regards,

    Cole Wu


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, July 8, 2016 12:57 AM
    Moderator
  • Hi Cole Wu,

    I am logging the connection state. It says connection closed. After getting this error my service stops responding to client calls. But after few hours my service starts responding to the client calls. This process repeats daily once.

    But if I recycle the App Pool of the Service in IIS it works fine for 2 to 3 days. Again above issue starts and repeats.

    Thanks in advance.

    Ravi.


    Ravishankar Boyina

    Monday, July 11, 2016 6:34 AM
  • Hi Ravishankar Boyina,

    According to your description, your logging shows that connection closed. it seems that you app run close method. maybe other code cause the issue. as I said above, I would suggest that you could use unit of work instead of singleton pattern.

    Best regards,

    Cole Wu


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Wednesday, July 13, 2016 6:12 AM
    Moderator
  • Hi Cole Wu,

    When I checked my APP POOL  worker process i.e w3wp.exe show 100% increase in memory consumption in Task Manager after 15 hrs of start of APP POOL(eg : when i started app pool memory consumption is about 60MB but after 15 hrs it shows as 120MB).

    When I run nestat -n command in cmd the it shows about 80 to 90 established connections. I didn't change the default connection pool size(100).

    After 20 to 24 hrs from start of app pool this error occurs for me. For every minute API opens about 5 connections and closes them.

    Should I do any changes in APP POOL settings ? For eg like queue length or queue size or change the idle time or any thing else?

    Thanks,

    Ravi.


    Ravishankar Boyina

    Wednesday, July 13, 2016 5:51 PM
  • Hi Ravishankar Boyina,

    I would suggest that you could read the following article about How to decide on a lifetime for your ObjectContext,

    maybe it will give you some idea to resolve the issue.

    http://blogs.msdn.com/b/alexj/archive/2009/05/07/tip-18-how-to-decide-on-a-lifetime-for-your-objectcontext.aspx.

    Best regards,

    Cole Wu


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Thursday, July 14, 2016 8:56 AM
    Moderator
  • Hi Cole Wu,

    Thanks for your reply. I found the issue and fixed it. I am using Owin and OAuth for authentication of Web API calls. First call for API is getting access token. I am connecting to DB to authenticate the request to give access token and after connecting to DB I am not closing. The access token is 15mins valid. So client is calling every 15 mins once to access token URL for getting new token. So every 15 mins one new connection is opening and it is not getting closed. When client call accesstoken URL request doesn't go through the MessageHandler what i have written. I found this issue by using Entity Framework Profiler.

    Now I am facing new issue . i.e Thread Safety. Scenario is,  my client is calling my API of same method URL's with very frequently with less than 1 sec gap. Due to this  data inconsistency is occurring mostly through PUT and POST methods. For example client is calling my POST method URL so frequently , before it finishes inserting a record into db once more web request is coming for this same POST method. So this results duplicate records in db.

    The link provided in your recent reply it has below point 

    • Thread Safety: 
      If you are trying to re-use an ObjectContext you should be aware that is not thread safe, i.e. similar to the standard .NET collection classes. If you access it from many threads (e.g. web requests) you will need to insure that you synchronize access manually.

    Actually here for every web request i am creating new ObjectContext. So If want apply Thread Safety from many Web Requests(many threads) so that above problem can solved.

    My solution is to use lock in POST method on certain logic which is causing above issue. Can you guide me the best way or best practice for above problem? How to synchronize access manually? 

    Best Regards,


    Ravishankar Boyina


    Sunday, July 24, 2016 5:49 PM
  • You know there is a Web API forum, right? You need to go post to it, because what you are doing seems very sketchy to say the least about it. 

    http://forums.asp.net/1246.aspx/1?Web+API

    Sunday, July 24, 2016 8:42 PM