Wondering if anyone has encountered this weird behaviour with Castle Windsor 3.0? I've set up the Container Configuration for the DbContext to have a lifestyle of PerWebRequest, but Castle does not dispose the Component after a WebRequest. It keeps the component in the Container across web requests as if it were a Singleton.
The problem that make this obvious is when there is a Database Error in the DbContext, it prevents all future CRUD operations from being actioned until IIS is restarted (i.e. manually destroying the DbContext)! This, as we know, is not acceptable.
If the DbContext is recycled PerWebRequest, then when the page is reloaded, other CRUD operations would be actioned successfully since we now have a new DbContext.
My Config is below:
private static IWindsorContainer InitializeWindsor()
{
var container = new WindsorContainer();
// Add Factory facility
container.AddFacility<TypedFactoryFacility>();
// Add AOP facility
container.AddFacility<AdditionalFunctionalityFacility>();
// Register all controllers from this assembly
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
container.Register(
Classes.FromAssembly(assembly).BasedOn<Controller>().Configure(c => c.LifestyleTransient())
);
}
// Adding logging facility. This has to happen after Controller registration, otherwise it bombs out
container.AddFacility<LoggingFacility>(f => f.UseLog4Net());
// Register HTTP Handlers
container.Register(Component.For<HttpRequestBase>().LifeStyle.PerWebRequest
.UsingFactoryMethod(() => new HttpRequestWrapper(HttpContext.Current.Request)));
container.Register(Component.For<HttpContextBase>().LifeStyle.PerWebRequest
.UsingFactoryMethod(() => new HttpContextWrapper(HttpContext.Current)));
// Register components
container.Register(
// Factories - singletons
Component.For<IServiceFactory>().LifeStyle.PerWebRequest.LifeStyle.Is(LifestyleType.Thread).AsFactory(),
Component.For<IDataFactory>().LifeStyle.PerWebRequest.LifeStyle.Is(LifestyleType.Thread).AsFactory(),
// Services
Component.For<IRegionService>().ImplementedBy<RegionService>().LifeStyle.PerWebRequest,
// Data Managers
Component.For<IRegionManager>().ImplementedBy<RegionManager>().LifeStyle.PerWebRequest,
// Data Contexts
Component.For<DbContext>().ImplementedBy<MyDataContext>().LifeStyle.PerWebRequest.LifeStyle.Is(LifestyleType.Thread)
);
return container;
}
My DbContext class is below:
public partial class MyDataContext : DbContext
{
static MyDataContext()
{
Database.SetInitializer<MyDataContext>(null);
}
public MyDataContext() : base("name=MyDataContext")
{
}
public MyDataContext(string nameOrConnectionString) : base(nameOrConnectionString)
{
}
public MyDataContext(string nameOrConnectionString, DbCompiledModel model) : base(nameOrConnectionString, model)
{
}
public MyDataContext(DbConnection existingConnection, bool contextOwnsConnection) : base(existingConnection, contextOwnsConnection)
{
}
public MyDataContext(DbConnection existingConnection, DbCompiledModel model, bool contextOwnsConnection) : base(existingConnection, model, contextOwnsConnection)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
modelBuilder.Configurations.Add(new Region_Mapping());
}
public DbSet<Region> Regions { get; set; }
}
Any help/suggestions would be highly appreciated.
Thanks.