2
votes

If I open a dbContext as a global variable, as in the code below, can it lead to connection pool problems compared to using a new datacontext in each function and wrapping it in a using block?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using LoopinDeals.Helper;

namespace LoopinDeals.Model
{
    public class DealUsersRepository
    {
        private DataClassesDataContext DbContext = new DataClassesDataContext();

        public void AddUser(string Email, string Password)
        {
            DealUser deal = new DealUser()
            {
                Email = Email,
                Password = Password,
                EmailVerified = true,
                LastLogin = DateTime.Now,
                AccountCreated = DateTime.Now,
                IsActive = true,
                RegistrationMethod = RegistrationType.Normal.ToString(),
                Subscribe = "true"
            };

            DbContext.DealUsers.InsertOnSubmit(deal);
            DbContext.SubmitChanges();
        }

        public void AddSignUpUser(string Email, string City)
        {
            try
            {
                DealUser UserData = new DealUser()
                    {
                        Email = Email,
                        City = City,
                        IsActive = false,
                        LastLogin = DateTime.Now
                    };
                DbContext.DealUsers.InsertOnSubmit(UserData);
            }
            catch (Exception ex)
            {               

            }
        }

        public void UpdateSignUpUser(string Email, string FirstName, string LastName, string Password, string Mobile, string City)
        {
            try
            {
                DealUser UserData = DbContext.DealUsers.Single(UD => UD.Email == Email);
                UserData.FirstName = FirstName;
                UserData.LastName = LastName;
                UserData.Password = Password;
                UserData.Mobile = Mobile;
                UserData.City = City;
                UserData.IsActive = true;
                UserData.LastLogin = DateTime.Now;
                DbContext.SubmitChanges();
            }
            catch (Exception ex)
            {

            }
        }


    }
}

Description

Please note that I did not write this code, it was outsourced. It crashes with the following error message and I am trying to figure out how to fix it.

Server Error in '/' Application. 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. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: 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.

Source Error:

[No relevant source lines]

Source File: c:\Windows\Microsoft.NET\Framework64\v2.0.50727\Temporary ASP.NET Files\root\f44daa26\cce00cbd\App_Web_b21g2v5x.5.cs Line: 0

Stack Trace:

[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.]
System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection) +6264689
System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) +6265031
System.Data.SqlClient.SqlConnection.Open() +258
System.Data.Linq.SqlClient.SqlConnectionManager.UseConnection(IConnectionUser user) +65 System.Data.Linq.SqlClient.SqlProvider.get_IsSqlCe() +33 System.Data.Linq.SqlClient.SqlProvider.InitializeProviderMode() +32
System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query) +63
System.Data.Linq.DataQuery`1.System.Collections.Generic.IEnumerable.GetEnumerator() +45 LoopinDeals.Model.SiteDetails..ctor() +253 LoopinDeals.Admin.Default..ctor() +76
ASP.admin_default_aspx..ctor() in c:\Windows\Microsoft.NET\Framework64\v2.0.50727\Temporary ASP.NET Files\root\f44daa26\cce00cbd\App_Web_b21g2v5x.5.cs:0
__ASP.FastObjectFactory_app_web_b21g2v5x.Create_ASP_admin_default_aspx() in c:\Windows\Microsoft.NET\Framework64\v2.0.50727\Temporary ASP.NET Files\root\f44daa26\cce00cbd\App_Web_b21g2v5x.22.cs:0
System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(VirtualPath virtualPath, Type requiredBaseType, HttpContext context, Boolean allowCrossApp, Boolean noAssert) +138
System.Web.UI.PageHandlerFactory.GetHandlerHelper(HttpContext context, String requestType, VirtualPath virtualPath, String physicalPath) +50 System.Web.MaterializeHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +425 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +263

I have added the SiteDetailsConstructor here, is it possible that this lead to connection pool problems ?

    public class SiteDetails
    {
        public DataClassesDataContext DbContext = new DataClassesDataContext();

        public SiteDetails()
        {
            var Details = from dtl in DbContext.SiteSettings
                          select dtl;

            foreach (var item in Details)
            {
                MetaIndexKeyword = item.MetaIndexKeyword;
                MetaIndexDesc = item.MetaIndexDesc;
                MetaIndexTitle = item.MetaIndexTitle;
                MetaGetPrefrenceKeyword = item.MetaGetPrefrenceKeyword;
                MetaGetPrefrenceDesc = item.MetaGetPrefrenceDesc;
                Logo = item.Logo;
                Favicon = item.Favicon;
                NoImage = item.NoImage;
                SiteName = item.SiteName;
                SiteTitle = item.SiteTitle;
                SiteUrl = item.SiteUrl;
                FbAndTwitterShareMessage = item.FbAndTwitterShareMessage;
                CharacterSet = item.CharacterSet;
                SiteMaintanance = item.SiteMaintanance;
                PasswordChar = item.PasswordChar;
                HtmlMetaKeyword = item.HtmlMetaKeyword;
                HtmlMetaDescription = item.HtmlMetaDescription;
                MetaDataGoogleSiteMap = item.MetaDataGoogleSiteMap;
                WebMasterEmail = item.WebMasterEmail;
                SupportEmail = item.SupportEmail;
                NoReplyName = item.NoReplyName;
                NoReplyEmail = item.NoReplyEmail;
                DeleteExpireDeals = item.DeleteExpireDeals;
                DealsPerPageBeforeLogin = item.DealsPerPageBeforeLogin;
                DealsPerPageAfterLogin = item.DealsPerPageAfterLogin;
                RecentViewDeals = item.RecentViewDeals;
                BoughtDeals = item.BoughtDeals;
                FbFanPage = item.FacebookFanPage;
                FbApplicationId = item.FbApplicationId;
                FbSecret = item.FbSecret;
                FbApiSharingDeals = item.FbApiSharingDeals;
                GoogleApiKey = item.GoogleApiKey;
                TwitterScreenName = item.TwitterScreenName;
                TwitterConsumerKey = item.TwitterConsumerKey;
                TwitterConsumerSecret = item.TwitterConsumerSecret;
                SharingAppId = item.SharingAppId;
                SharingAppSecret = item.SharingAppSecret;
                SharingCanvasURL = item.SharingCanvasURL;
                InviteMessage = item.InviteMessage;
                SharingMsgLink = item.SharingMsgLink;
                ShareMsgPicture = item.ShareMsgPicture;
                ShareMsgName = item.ShareMsgName;
                ShareMsgCaption = item.ShareMsgCaption;
                ShareMsgDesc = item.ShareMsgDesc;
            }

        }

        public static string MetaIndexKeyword { get; set; }
        public static string MetaIndexDesc { get; set; }
        public static string MetaIndexTitle { get; set; }
        public static string MetaGetPrefrenceKeyword { get; set; }
        public static string MetaGetPrefrenceDesc { get; set; }
        public static string Logo { get; set; }
        public static string Favicon { get; set; }
        public static string NoImage { get; set; }
        public static string SiteName { get; set; }
        public static string SiteTitle { get; set; }
        public static string SiteUrl { get; set; }
        public static string FbAndTwitterShareMessage { get; set; }
        public static string CharacterSet { get; set; }
        public static string SiteMaintanance { get; set; }
        public static string PasswordChar { get; set; }
        public static string HtmlMetaKeyword { get; set; }
        public static string HtmlMetaDescription { get; set; }
        public static string MetaDataGoogleSiteMap { get; set; }
        public static string WebMasterEmail { get; set; }
        public static string SupportEmail { get; set; }
        public static string NoReplyName { get; set; }
        public static string NoReplyEmail { get; set; }
        public static bool? DeleteExpireDeals { get; set; }
        public static int? DealsPerPageBeforeLogin { get; set; }
        public static int? DealsPerPageAfterLogin { get; set; }
        public static int? RecentViewDeals { get; set; }
        public static int? BoughtDeals { get; set; }
        public static string FbFanPage { get; set; }
        public static string FbApplicationId { get; set; }
        public static string FbSecret { get; set; }
        public static string FbApiSharingDeals { get; set; }
        public static string GoogleApiKey { get; set; }
        public static string TwitterScreenName { get; set; }
        public static string TwitterConsumerKey { get; set; }
        public static string TwitterConsumerSecret { get; set; }

        public static string SharingAppId { get; set; }
        public static string SharingAppSecret { get; set; }
        public static string SharingCanvasURL { get; set; }
        public static string InviteMessage { get; set; }
        public static string SharingMsgLink { get; set; }
        public static string ShareMsgPicture { get; set; }
        public static string ShareMsgName { get; set; }
        public static string ShareMsgCaption { get; set; }
        public static string ShareMsgDesc { get; set; }

    }
}
2

2 Answers

6
votes

It should not lead to connection pool problems, since the DB connection is only opened, used and closed when you call SubmitChanges.

Since DBContext is not thread-safe it will cause problems though if your repository instance is used by multiple threads.

Another problem will be caching of data done by EF within the DBContext instance - if you do not dispose the DBContext instance, this cached data will accumulate and can grow quite large after some time to the point that it is causing memory pressure.

For both of these reasons (and there not being much overhead for re-creating contexts) it is overall just better practice to keep the DBContext usage within a using block.

5
votes

Having the context managed globally will not lead to connection pool problems. However, the context contains the DBSets with all of the data accessed so the context will grow until you run out of memory (assuming your DB is larger than your available memory).

But the context is cheap to create, why would you want to manage it globally?

-- Response to new information

I don't think the code fragment you are showing is behind the issue at all. Rather, from looking at the code trace, the issue appears to be happening in the constuctor for SiteDetails. is this constructor loading a lot of data? if os, you could simply be overwhelming the database because too many threads are trying to load too much data.