我的自定义 MembershipProvider 中 Ninject 注入的 ObjectContext 的范围是什么(使用 Request 范围)?
我使用 Entity Framework 4 和 ASP.NET MVC 3。我创建了一个自定义成员资格提供程序,并使用 Ninject 将 EFAccountRepository 注入其中(将 IAccountRepository 绑定到 EFAccountRepository)。
该帐户存储库已注入一个 ObjectContext。我还在我的控制器中使用这个存储库(和其他存储库)。因此,当我将 IContext 绑定到 ObjectContext 时,我将范围设置为“每个请求”,以便 ObjectContext 仅存在于一个请求中并在存储库之间共享。
我在尝试登录时有时会收到以下错误:“ObjectContext 实例已被释放,无法再用于需要连接的操作。”
我想知道会员资格提供者多久被实例化一次。我通过使用 [Inject]
标记存储库属性并在全局的 Application_Start
函数中调用 Kernel.Inject
将存储库注入到成员资格提供程序中。 .asax 文件。
如果提供者被实例化多次,我想我将不得不再次注入。但是,我没有得到空指针异常,所以我认为不是这样的。
更新 1
以下是一些代码:
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 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 error 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 ;).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
异常表明您错误地处理了上下文。在某个地方您调用了context.Dispose(或者在using中拥有上下文),但之后您想再次使用上下文,这是不可能的,因为上下文已经被释放。如果您使用每个请求上下文,则必须在请求处理结束时仅处理一次上下文(当您确定没有代码将使用该上下文时)。
The exception says that you are incorrectly handling disposing of your context. Somewhere you call
context.Dispose
(or have context inusing
) 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).您没有指定 EFAccountRepository 绑定的范围,因此它默认为 .InTransientScope()。这意味着每次解析 IAccountRepository 时都会创建该对象的一个新实例 [请参阅 https ://github.com/ninject/ninject/wiki/Object-Scopes]。
瞬态范围对象
相比之下,您将 MyObjectContext 绑定到 IObjectContext .InRequestScope()。这意味着当您处于相同的 HTTP 请求处理操作中时,它将被重用。
此外,在 http 请求完成之前,请求范围对象
现在,ObjectContext 是 IDisposable,因此可以合理地得出结论:
为了解决这个问题,您需要弄清楚为什么您的对象上下文对象引用能够存活这么长时间,并考虑消除长寿命......或删除其对短寿命(请求范围)对象的依赖。
[清楚地注意这个问题已经有一个公认的答案,但我认为公认的答案有点难以理解。]
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
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
Now, ObjectContext is IDisposable, so it seems reasonable to conclude that
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.]