我正在创建一个Web API,我正在使用依赖注入Ninject。
我有:
IRTWRepository IModelFactory
我正在将这些2注入我的控制器中。
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IRTWRepository>().To<RTWRepository>();
kernel.Bind<RTWAPIContext>().To<RTWAPIContext>();
kernel.Bind<IModelFactory>().To<ModelFactory>();
}
我的RTWRepository构造函数看起来像这样
public class RTWRepository :IRTWRepository
{
private RTWAPIContext _context;
public RTWRepository(RTWAPIContext context)
{
_context = context;
}}
我的ModelFactory构造函数看起来像这样
public class ModelFactory : IModelFactory
{
private IRTWRepository _repo;
public ModelFactory(IRTWRepository repo)
{
_repo = repo;
}
}
我有一个看起来像这样的控制器:
public MaterialsController(IRTWRepository repository,IModelFactory modelFactory)
: base(repository,modelFactory)
{
}
现在,我的问题是:在创建RTWRepository的实例时以及在创建ModelFactory实例时,Ninject是否创建了2个单独的上下文?
我问的原因是因为当我尝试保存一个依赖于之前从数据库中检索的另一个对象的实体时,我遇到了问题。
我正在我的控制器中保存实体,但我在我的模型工厂中创建它是依赖。
public class RecycleCenter
{
public RecycleCenter()
{
}
public int MyProperty { get; set; }
[Required]
public virtual Address Address { get; set; }
}
上面的代码是针对具有地址的实体回收中心,这个回收中心实体是在我的模型工厂中创建的,然后在我的控制器中我尝试保存它但是当我的存储库执行此行时
_context.RecycleCenters.Add(entity);
我收到此错误
An entity object cannot be referenced by multiple instances of IEntityChangeTracker
所以,在我的代码中的某个地方,我使用的是2个上下文而不是1个,我认为在创建ModelFactory
和RTWRepository
时,这个假设是正确的吗?如果是这样,我该如何修复它?
答案 0 :(得分:1)
最有可能的是,它是。没有注释告诉Ninject&#34;嘿,停止,当你创建一次实例时,重用它&#34;。你应该同意,在大多数情况下,你会想要一个对象的多个实例,这是一种罕见的情况,只需要一次。
如果要重用实例,请使用单例模式。 Ninject熟悉它,因此您可以将对象映射绑定到方法
kernel.Bind<RTWAPIContext>().ToMethod(c => RTWAPIContext.GetInstance());
还有一个ToSingleton
绑定,但我敢打赌,由于其他ASP.NET问题,你不能让你的上下文构造函数私有并实现C#特定单例(例如ASP.NET身份将尝试调用上下文&#39 ; s用于创建对象的方法。)
答案 1 :(得分:1)
TL; DR;
您可能需要更改此行:
kernel.Bind<RTWAPIContext>().To<RTWAPIContext>();
到
kernel.Bind<RTWAPIContext>().To<RTWAPIContext>().InRequestContext();
说明:
在Ninject中定义绑定时,还要指定应如何处理该对象的生命周期。
如果您没有明确定义它,Ninject的默认生命周期为Transient
。 Transient
表示每次需要实例时,都会创建一个新实例。在您的情况下,您需要两个实例:一个用于RTWRepository
的{{1}},另一个用于ModelFactory
的{{1}}。
您可以将生活方式修改为以下选项之一:
RTWRepository
MaterialsController
kernel.Bind<RTWAPIContext>().To<RTWAPIContext>().InSingleTonScope();
在您的情况下,我认为您需要kernel.Bind<RTWAPIContext>().To<RTWAPIContext>().InRequestScope();
,但您必须检查必要的生命周期,因为它取决于应用程序。
有关详细信息,请查看此处的文档:https://github.com/ninject/ninject/wiki/Object-Scopes