What is the scope of my ObjectContext introduced by Ninject in my custom member package (using the request scope)?

I use Entity Framework 4 and ASP.NET MVC 3. I created a custom membership provider and use Ninject to insert an EFAccountRepository (Bound IAccountRepository - EFAccountRepository) into it.

This account repository has an ObjectContext. I also use this repository (and others) in my controllers. For this reason, when I attached an IContext to an ObjectContext, I set the scope to "request", so the ObjectContext lives in only one request and is shared between repositories.

Sometimes, when trying to log in, the following error occurs: "The ObjectContext instance has been deleted and can no longer be used for operations that require a connection."

I wonder how often an instance of a membership provider is created. I entered the repository into the membership provider by [Inject] repository property and calling Kernel.Inject in the Application_Start function in the global.asax file.

If the provider receives the instance more than once, I must enter it again, I suppose. However, I am not getting a null pointer exception, so I don't think so.

Update 1

Here is the code:

MyNinjectModule.cs

  public override void Load() { Bind<IMyContext>().To<MyObjectContext>().InRequestScope(); // put bindings here Bind<IAccountRepository>().To<EFAccountRepository> } 

Global.asax

  protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); var kernel = new StandardKernel(new MyNinjectModule()); ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(kernel)); kernel.Inject(Membership.Provider); } 

MyMembershipProvider.cs

  [Inject] public IAccountRepository accountRepository { get; set; } public override bool ValidateUser(string username, string password) { // I get the exception here. return (from a in accountRepository.Accounts where a.UserName == username && a.Password == password select true).SingleOrDefault(); } 

EFAccountRepository.cs

  private readonly IMyContext context; public EFAccountRepository(IMyContext context) { this.context = context; } public IQueryable<Account> Accounts { get { return context.Accounts; } } 

MyObjectContext.cs

 public class MyObjectContext : ObjectContext, IMyContext { public IObjectSet<Account> Accounts { get; private set; } public FlorenceObjectContext() : this("name=DomainModelContainer") { } public FlorenceObjectContext(string connectionString) : base(connectionString, "DomainModelContainer") { Accounts = CreateObjectSet<Account>(); } } 

PS: I am always open for comments on my code in general;).

+7
source share
2 answers

The exception indicates that you are not handling the deletion of your context correctly. Somewhere you call context.Dispose (or have a context in using ), but after that you want to use the context again, which is impossible, because the context has already been deleted. If you use the context for the request, you should only place the context at the end of the request processing (when you are sure that no code will use the context).

+3
source

You did not specify the scope for the EFAccountRepository binding, so it defaults to .InTransientScope (). This means that a new instance of the object will be created each time IAccountRepository is resolved [see https://github.com/ninject/ninject/wiki/Object-Scopes ].

In addition, the transition area objects

  • garbage is automatically collected as soon as there is no reference to them [Ninject does not cache them]
  • not automatically deleted by anyone

In contrast, you bound MyObjectContext to IObjectContext.InRequestScope (). This means that it will be reused when you perform an HTTP request processing operation.

In addition, the query scope object

  • garbage will not be collected until your HTTP request is completed.
  • can be automatically deleted as soon as the HTTP request is completed, if it is IDisposable. [Not sure exactly when, but from the other questions I saw, I suspect that it depends on the version of Ninject]

Now ObjectContext is IDisposable, so it seems reasonable to conclude that

  • there is a reference to the IObjectContext object, and you use the IObjectContext outside the HTTP request that was created.
  • Ninject automatically deleted it since the HTTP request was completed.

To solve this problem, you need to find out why the link to the object-object of the object is kept for so long, and consider either eliminating the longevity ... or removing its dependence on the short-lived (taking into account the requests) objects.

[note that the question already has an accepted answer, but I think the accepted answer was pretty hard to understand.]

0
source

All Articles