This is in C# ASP.NET MVC 5 with Entity Framework 6, .NET 4.8, MySql, IIS.
I seem to be getting a race condition here:
LogErr("set AppAgent start");
_AppWebsite = db.Websites
.Where(x => x.Domain == Request.Url.Host)
.SingleOrDefault();
LogErr("set AppAgent end");
My log shows "set AppAgent start" but not "set AppAgent start", so it is hanging on the db access. It doesn't seem to be giving an exception.
The hang / race is easy to catch after a fresh publish. If I make multiple requests while the site is starting up it will usually hang. It would probably happen at other times but I can't make those requests quickly enough to cause the hang once it's running.
Killing the AppPool will fix the hang.
Here's the controller. It's a base controller I derive from. I've removed a lot of code of course.
I hope someone can tell me what I'm doing wrong here.
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Threading;
using System.Net;
using System.Web;
using System.Web.Mvc;
using System.Security.Claims;
using System.Globalization;
using PropertyDB;
using PropertyDB.Models;
using PropertyDB.Support;
using PropertySite.Models;
using PropertySite.Support;
using System.IO;
namespace PropertySite.Controllers
{
public class BaseController : Controller
{
protected DataContext db = new PropertyDB.DataContext();
protected PageModel DefaultPageModel;
private Website _AppWebsite; //cache for AppWebsite
public Website AppWebsite
{
get
{
if (_AppWebsite == null)
{
LogErr("set AppAgent start");
_AppWebsite = db.Websites.Where(x => x.Domain == Request.Url.Host).SingleOrDefault();
LogErr("set AppAgent end");
}
return _AppWebsite;
}
}
public BaseController()
{
}
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
//init model for page
string RequestPath = Request.Path;
DefaultPageModel = new PageModel()
{
Website = AppWebsite,
Route = RequestPath.Substring(1).Split('/'),
};
string PagePath = DefaultPageModel.Route[0];
DefaultPageModel.Page = db.Pages
.Where(x => x.WebsiteId == AppWebsite.Id)
.Where(x => x.Path == PagePath)
.SingleOrDefault();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (db != null)
{
db.Dispose();
db = null;
}
}
base.Dispose(disposing);
}
}
}
and the table it is querying is below. The table has 5 records.
CREATE TABLE `websites` (
`Id` int NOT NULL AUTO_INCREMENT,
`SellerId` int NOT NULL,
`Name` varchar(45) NOT NULL,
`Domain` varchar(50) DEFAULT NULL,
`MenuH` varchar(150) DEFAULT '',
`MenuF` varchar(150) DEFAULT '',
`CreatedDate` datetime DEFAULT NULL,
`DeletedDate` datetime DEFAULT NULL,
`SubEndDate` date DEFAULT '2090-01-01',
`Logo` varchar(30) DEFAULT NULL,
PRIMARY KEY (`Id`),
UNIQUE KEY `i_SellerId` (`SellerId`),
KEY `i_Domain` (`Domain`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
I've tried moving the code from OnActionExecuting
to the Initialize
method, but it didn't help.
This is in C# ASP.NET MVC 5 with Entity Framework 6, .NET 4.8, MySql, IIS.
I seem to be getting a race condition here:
LogErr("set AppAgent start");
_AppWebsite = db.Websites
.Where(x => x.Domain == Request.Url.Host)
.SingleOrDefault();
LogErr("set AppAgent end");
My log shows "set AppAgent start" but not "set AppAgent start", so it is hanging on the db access. It doesn't seem to be giving an exception.
The hang / race is easy to catch after a fresh publish. If I make multiple requests while the site is starting up it will usually hang. It would probably happen at other times but I can't make those requests quickly enough to cause the hang once it's running.
Killing the AppPool will fix the hang.
Here's the controller. It's a base controller I derive from. I've removed a lot of code of course.
I hope someone can tell me what I'm doing wrong here.
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Threading;
using System.Net;
using System.Web;
using System.Web.Mvc;
using System.Security.Claims;
using System.Globalization;
using PropertyDB;
using PropertyDB.Models;
using PropertyDB.Support;
using PropertySite.Models;
using PropertySite.Support;
using System.IO;
namespace PropertySite.Controllers
{
public class BaseController : Controller
{
protected DataContext db = new PropertyDB.DataContext();
protected PageModel DefaultPageModel;
private Website _AppWebsite; //cache for AppWebsite
public Website AppWebsite
{
get
{
if (_AppWebsite == null)
{
LogErr("set AppAgent start");
_AppWebsite = db.Websites.Where(x => x.Domain == Request.Url.Host).SingleOrDefault();
LogErr("set AppAgent end");
}
return _AppWebsite;
}
}
public BaseController()
{
}
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
//init model for page
string RequestPath = Request.Path;
DefaultPageModel = new PageModel()
{
Website = AppWebsite,
Route = RequestPath.Substring(1).Split('/'),
};
string PagePath = DefaultPageModel.Route[0];
DefaultPageModel.Page = db.Pages
.Where(x => x.WebsiteId == AppWebsite.Id)
.Where(x => x.Path == PagePath)
.SingleOrDefault();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (db != null)
{
db.Dispose();
db = null;
}
}
base.Dispose(disposing);
}
}
}
and the table it is querying is below. The table has 5 records.
CREATE TABLE `websites` (
`Id` int NOT NULL AUTO_INCREMENT,
`SellerId` int NOT NULL,
`Name` varchar(45) NOT NULL,
`Domain` varchar(50) DEFAULT NULL,
`MenuH` varchar(150) DEFAULT '',
`MenuF` varchar(150) DEFAULT '',
`CreatedDate` datetime DEFAULT NULL,
`DeletedDate` datetime DEFAULT NULL,
`SubEndDate` date DEFAULT '2090-01-01',
`Logo` varchar(30) DEFAULT NULL,
PRIMARY KEY (`Id`),
UNIQUE KEY `i_SellerId` (`SellerId`),
KEY `i_Domain` (`Domain`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
I've tried moving the code from OnActionExecuting
to the Initialize
method, but it didn't help.
1 Answer
Reset to default 0This seems to be fixed now thanks to some housekeeping. I was about to start cutting the app down to narrow down the cause, so I did some tidying up first. I don't know the exact cause but here's what I did:
- Updated all nuget packages. This included a lot of minor version updates to EF and MySql.data.
- I removed references in web.config to Owin components. The nuget packages had been uninstalled, but these references remained.
- Clean the project and rebuild.
I suspect it was the owin references in web.config causing the problem.
public Website AppWebsite
would instantiate_AppWebsite
multiple times, but that is not going to happen here. Have you actually verified there isn't an exception? – GSerg Commented Nov 17, 2024 at 15:52CREATE TABLE
for the table it is querying. – mjwills Commented Nov 17, 2024 at 22:34private Website _AppWebsite; //cache for AppAgent
in what way is this a cache. You are aware that each web request will new up a new instance of the controller (and thus thatWebsite
is not shared between requests)? – mjwills Commented Nov 17, 2024 at 22:36it's a cahce in the sense
no it's not. A new controller instance is created for every request, so_AppWebsite
is always null. – Panagiotis Kanavos Commented Nov 18, 2024 at 12:48SELECT FOR UPDATE
, either in the application or MySQL Workbench? – Panagiotis Kanavos Commented Nov 18, 2024 at 14:06