I have a pretty complicated problem. I'm using FluentValidation.MVC in my ASP.NET MVC 5 project. In it, I use a repository pattern to check whether a user's email address is not duplicated. The issue isn't really the repository pattern; it's that the repository uses an Entity Framework context injected into the constructor at run time:
public class SomeRepository
{
//IEFContext is something I modified the T4 template to generate
public SomeRepository(IEFContext context)
{
_context = context;
}
}
The application uses this approach and it works great. SimpleInjector wires up my EF context, which is scoped to use the Per ASP.NET web request (wraps around HttpContext.Items).
Dim httpLifecycle = New SimpleInjector.Integration.Web.WebRequestLifestyle(True)
container.Register(of IEFContext, EFContext)(httpLifecycle)
No issues with the app here, just the validation. When the server receives the post operation, the error I'm getting is "The operation cannot be completed because the DbContext has been disposed". It appears I cannot use any EF-related code in a FluentValidation attribute, which uses an EF context on a per web request basis. Nothing special about the validation attribute, which does:
public class Val : AbstractValidator<Entity>
{
public Val()
{
_repos = Container.GetInstance<ISomeRepos>();
RuleFor(i => i.Email).Must((o, v) =>
{
_repos.HasDistinctEmail(o.ID, v);
}
}
}
The context should have died with the previous request since stored in HttpContext.Items
. Any idea what's going on? I know by setting True to the WebRequestLifecycle
, I am causing the EF context to be disposed on request end. I would think that would be desirable.
My best bet is that an instance of the Val
class is cached for the duration of the AppDomain (a singleton), which means that its constructor is called just once and therefore it only resolves one single ISomeRepos
, causing that repo to be promoted to singleton as well (and with it, all its dependencies).
The quick fix is simple, move the GetInstance
call inside the delegate:
public Val()
{
RuleFor(i => i.Email).Must((o, v) =>
{
repos = Container.GetInstance<ISomeRepos>();
repos.HasDistinctEmail(o.ID, v);
}
}
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