It doesn't happen often but from time to time I'll get an exception report emailed to me pointing to this bit of code. I'm wondering if you see anything wrong with the following code. I cannot get it to fail locally and tracing the data using breakpoints always gives the correct results, step by step.
namespace DomainModel.Concrete
{
public class ConfigRepository : IConfigRepository
{
static mvCmsContext context { get; set; }
public ConfigRepository() { context = new mvCmsContext(); }
private static Func<mvCmsContext, string, Configuration> _byName =
CompiledQuery.Compile((mvCmsContext context, string configName) =>
(from c in context.Configs
where c.configName == configName
select c).SingleOrDefault());
static public Configuration ByName(string configName)
{
var result = (Configuration)HttpContext.Current.Cache.Get(configName);
if (result == null)
{
using (new mvCmsContext())
{
HttpContext.Current.Cache.Insert(configName, _byName(context, configName));
result = (Configuration)HttpContext.Current.Cache.Get(configName);
}
}
return result;
}
}
}
Here is the service calling that method:
public class ConfigService
{
public static string siteName
{
get { return ConfigRepository.ByName("Site_Name").configValue; }
}
public static string copyright
{
get { return ConfigRepository.ByName("Copyright").configValue; }
}
public static string companyName
{
get { return ConfigRepository.ByName("Company_Name").configValue; }
}
public static string homeTitle
{
get { return ConfigRepository.ByName("Home_Title").configValue; }
}
public static string contactEmail
{
get { return ConfigRepository.ByName("Contact_Email").configValue; }
}
public static string physicalAddress
{
get { return ConfigRepository.ByName("Physical_Address").configValue; }
}
public static string phoneNumber
{
get { return ConfigRepository.ByName("Phone_Number").configValue; }
}
}
Here is the report received:
** Summary ** --------------- This message contains events 1 to 1 from the total of 1 events scheduled for this notification. There were 0 events left in the buffer at the beginning of this notification.
** Application Information ** --------------- Application domain: /LM/W3SVC/66/ROOT-7-129384226573152341 Trust level: Full Application Virtual Path: / Application Path: D:*****.com\ Machine name: WIN11
** Events ** --------------- Event code: 3005 Event message: An unhandled exception has occurred. Event time: 1/2/2011 12:17:44 AM Event time (UTC): 1/2/2011 6:17:44 AM Event ID: f909c5c676bd4ca1ba21512c678ac502 Event sequence: 6 Event occurrence: 1 Event detail code: 0
Process information: Process ID: 26904 Process name: w3wp.exe Account name: NT AUTHORITY\NETWORK SERVICE
Exception information: Exception type: System.InvalidOperationException Exception message: Invalid operation. The connection is closed.
Request information: Request URL: http://.com/article/-ALERT Request path: /article/III-ALERT User host address: 68.230.129.53 User: Is authenticated: False Authentication Type: Thread account name: NT AUTHORITY\NETWORK SERVICE
Thread information: Thread ID: 6 Thread account name: NT AUTHORITY\NETWORK SERVICE Is impersonating: False Stack trace: at System.Data.SqlClient.SqlConnection.GetOpenConnection() at System.Data.SqlClient.SqlConnection.get_HasLocalTransactionFromAPI() at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method) at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior) at System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object lastResult) at System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries) at System.Data.Linq.SqlClient.SqlProvider.CompiledQuery.Execute(IProvider provider, Object[] arguments) at System.Data.Linq.CompiledQuery.ExecuteQuery(DataContext context, Object[] args) at System.Data.Linq.CompiledQuery.Invoke[TArg0,TArg1,TResult](TArg0 arg0, TArg1 arg1) at DomainModel.Concrete.ConfigRepository.ByName(String configName) at DomainModel.Services.ConfigService.get_companyName() at ASP.views_shared_site_master._Render_control1(HtmlTextWriter __w, Control parameterContainer) at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) at System.Web.UI.Page.Render(HtmlTextWriter writer) at System.Web.Mvc.ViewPage.Render(HtmlTextWriter writer) at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
If I were closing the datacontext at the wrong place it would fail all the time, wouldn't it?
Edit - Data context:
public class mvCmsContext : DataContext
{
public mvCmsContext():
base(ConfigurationManager.ConnectionStrings["ApplicationServices"].ConnectionString,XmlMappingSource.FromStream(Assembly.GetExecutingAssembly().GetManifestResourceStream("DomainModel.mvCmsMapping.map"))){
Log = (StringWriter)HttpContext.Current.Items["linqToSqlLog"];
}
public Table<DomainModel.Entities.Configuration> Configs { get { return this.GetTable<DomainModel.Entities.Configuration>(); } }
}
Edit to add update: Does this look better? I'll upload it and give it a go.
public class ConfigRepository : IConfigRepository
{
private mvCmsContext context { get; set; }
public ConfigRepository() { context = new mvCmsContext(); }
private static Func<mvCmsContext, string, Configuration> _byName =
CompiledQuery.Compile((mvCmsContext context, string configName) =>
(from c in context.Configs
where c.configName == configName
select c).SingleOrDefault());
static public Configuration ByName(string configName)
{
var result = (Configuration)HttpContext.Current.Cache.Get(configName);
if (result == null)
{
using (var context = new mvCmsContext())
{
HttpContext.Current.Cache.Insert(configName, _byName(context, configName));
result = (Configuration)HttpContext.Current.Cache.Get(configName);
}
}
return result;
}
Your issue is that you are defining your datacontext as static. This means its shared by all requests and threads.
When you have two different requests hitting your static datacontext, these sort of exceptions occur. Your using section in ByName will recreate and dispose of the datacontext, imagine another request is using the datacontext while your doing this....... hence the exceptions.
The solution is to make your datacontext non-static.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With