admin管理员组

文章数量:1025512

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.

Share Improve this question edited Nov 18, 2024 at 15:05 EamonnM asked Nov 17, 2024 at 14:50 EamonnMEamonnM 2,2911 gold badge15 silver badges19 bronze badges 19
  • Why do you think it's a race condition, and why would it be a problem if it were? Sure, you are not following any singleton patter, so multithreaded access to the 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:52
  • Please share the CREATE TABLE for the table it is querying. – mjwills Commented Nov 17, 2024 at 22:34
  • 2 private 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 that Website is not shared between requests)? – mjwills Commented Nov 17, 2024 at 22:36
  • 2 it'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:48
  • 1 That's not a deadlock either. The database would detect the deadlock and kill one of the connections that caused it. Post something that reproduces the problem so others can test it. Are you sure you have no code executing eg SELECT FOR UPDATE, either in the application or MySQL Workbench? – Panagiotis Kanavos Commented Nov 18, 2024 at 14:06
 |  Show 14 more comments

1 Answer 1

Reset to default 0

This 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.

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.

Share Improve this question edited Nov 18, 2024 at 15:05 EamonnM asked Nov 17, 2024 at 14:50 EamonnMEamonnM 2,2911 gold badge15 silver badges19 bronze badges 19
  • Why do you think it's a race condition, and why would it be a problem if it were? Sure, you are not following any singleton patter, so multithreaded access to the 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:52
  • Please share the CREATE TABLE for the table it is querying. – mjwills Commented Nov 17, 2024 at 22:34
  • 2 private 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 that Website is not shared between requests)? – mjwills Commented Nov 17, 2024 at 22:36
  • 2 it'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:48
  • 1 That's not a deadlock either. The database would detect the deadlock and kill one of the connections that caused it. Post something that reproduces the problem so others can test it. Are you sure you have no code executing eg SELECT FOR UPDATE, either in the application or MySQL Workbench? – Panagiotis Kanavos Commented Nov 18, 2024 at 14:06
 |  Show 14 more comments

1 Answer 1

Reset to default 0

This 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.

本文标签: cWhy does this ASPNET MVC controller hang the AppPool in IISStack Overflow