开发者

What is the scope of my Ninject injected ObjectContext in my custom MembershipProvider (using Request scope)?

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

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

I am sometimes get the following erro开发者_JAVA技巧r when trying to log in:"The ObjectContext instance has been disposed and can no longer be used for operations that require a connection."

I wonder how often the membership provider gets instantiated. I injected the repository into the membership provider by marking the repository property with [Inject] and calling Kernel.Inject in the Application_Start function in the global.asax file.

If the provider gets instantiated more than once I would have to inject again I suppose. However, I don't get a null pointer exception, so I don't think that's it.

Update 1

Here's some 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'm always open to comments on my code in general ;).


The exception says that you are incorrectly handling disposing of your context. Somewhere you call context.Dispose (or have context in using) but after that you want to use context again which is not possible because context is already disposed. If you are using per request context you must dispose context only once at the end of request processing (when you are sure that no code will use the context).


You didn't specify a scope for your EFAccountRepository binding so it defaults to .InTransientScope(). This means a new instance of the object will be created each time you resolve the IAccountRepository [refer to https://github.com/ninject/ninject/wiki/Object-Scopes ].

Also, transient scope objects

  1. are automatically garbage collected as soon as there are no references to them [Ninject doesn't cache them]
  2. are not automatically disposed by anyone

In contrast, you bound MyObjectContext to IObjectContext .InRequestScope(). This means it will be reused when you are in the same HTTP request handling operation.

Also, a request scope object

  1. won't be garbage collected until your http request is done
  2. might be automatically disposed once the HTTP request is done, if it's IDisposable. [Not sure precisely when, but from other questions I have seen I suspect it depends on the version of Ninject]

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

  • an object reference to the IObjectContext exists, and you are using the IObjectContext outside of the HTTP request which it was created in.
  • Ninject has automatically disposed of it, since the HTTP request has completed.

In order to solve the issue, you need to figure out why your object context object reference is surviving so long, and consider either eliminating the long-livedness... or removing its dependency on short-lived (request-scoped) objects.

[note clearly the question already has an accepted answer, but I think the accepted answer was kind of hard to understand.]

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜