使用 Ninject 和 Windows 服务的 InSingletonScope
我重新发布了这个问题,因为我认为它有点模糊。 新帖子
我目前使用的是 Windows 2 分钟计时器服务。我首先使用 EF 代码和存储库模式来进行数据访问。我正在使用 Ninject 来注入我的依赖项。我的 NinjectDependencyResolver 类中有以下绑定:
ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings["Database"];
Bind<IDatabaseFactory>().To<DatabaseFactory>()
.InSingletonScope()
.WithConstructorArgument("connectionString", connectionStringSettings.Name);
Bind<IUnitOfWork>().To<UnitOfWork>().InSingletonScope();
Bind<IMyRepository>().To<MyRepository>().InSingletonScope();
当我的服务每 2 分钟运行一次时,我会做一些类似的事情:
foreach (var row in rows)
{
var existing = myRepository.GetById(row.Id);
if (existing == null)
{
existing = new Row();
myRepository.Add(existing);
unitOfWork.Commit();
}
}
我开始在日志中看到一个错误,上面写着:
对数据库的更改已成功提交,但出现错误更新对象上下文时发生。 ObjectContext 可能处于不一致的状态。内部异常消息:AcceptChanges 无法继续,因为该对象的键值与 ObjectStateManager 中的另一个对象冲突。在调用 AcceptChanges 之前确保键值是唯一的。
在 Windows 服务中使用 Ninject 时使用 InSingeltonScope 是否正确?我相信我尝试使用不同的作用域,例如 InTransientScope,但我只能让 InSingeltonScope 来处理数据访问。错误消息与范围有关系还是无关?
I re-posted this question as I think it is a bit vague. New Post
I am currently using a Windows Service that is on a 2 minute timer. I am using EF code first with a repository pattern for data access. I am using Ninject to inject my dependencies. I have the following bindings in my NinjectDependencyResolver class:
ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings["Database"];
Bind<IDatabaseFactory>().To<DatabaseFactory>()
.InSingletonScope()
.WithConstructorArgument("connectionString", connectionStringSettings.Name);
Bind<IUnitOfWork>().To<UnitOfWork>().InSingletonScope();
Bind<IMyRepository>().To<MyRepository>().InSingletonScope();
When my service runs every 2 minutes I do some thing similar to this:
foreach (var row in rows)
{
var existing = myRepository.GetById(row.Id);
if (existing == null)
{
existing = new Row();
myRepository.Add(existing);
unitOfWork.Commit();
}
}
I am starting to see an error in my logs that say:
The changes to the database were committed successfully, but an error occurred while updating the object context. The ObjectContext might be in an inconsistent state. Inner exception message: AcceptChanges cannot continue because the object's key values conflict with another object in the ObjectStateManager. Make sure that the key values are unique before calling AcceptChanges.
Is it correct to use InSingeltonScope when using Ninject in a Windows Service? I believe I tried using different scopes like InTransientScope but I could only get InSingeltonScope to work with data access. Does the error message have anything to do with Scope or is it unrelated?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
假设该服务不是操作数据库的唯一进程,则不应使用 Singleton。在这种情况下发生的情况是,您正在重用已缓存过期实体的 DBContext。
更好的方法是以类似于 web/wcf 请求的方式处理服务的每个计时器执行,并为该请求创建一个新的作业处理器。
根据问题的不同,最好将循环放在外面,并为每一行配备一个新的处理器。
阅读 http://www.planetgeek.ch/2011/12 /31/ninject-extensions-factory-introduction/ 了解有关工厂的更多信息。如果您需要将 UoW 注入多个类,还可以查看命名范围扩展的 InCallScope。 http:// www.planetgeek.ch/2010/12/08/how-to-use-the-additional-ninject-scopes-of-namedscope/
Assuming that the service is not the only process that operates on the database you shouldn't use Singleton. What happens in this case is that you are reusing a DBContext that has cached entities which are out of date.
The better way is to treat each timer execution of the service in a similar way like it is a web/wcf request and create a new job processor for the request.
Depending of the problem it might even better to put the loop outside and have a new processor for each single row.
Read http://www.planetgeek.ch/2011/12/31/ninject-extensions-factory-introduction/ for more information about factories. Also have a look at the InCallScope of the named scope extension if you need to inject the UoW into multiple classes. http://www.planetgeek.ch/2010/12/08/how-to-use-the-additional-ninject-scopes-of-namedscope/
InSingletonScope
将为您的服务的整个生命周期创建一个单例上下文 = 一个上下文。这是非常糟糕的解决方案。由于上下文保存了所有先前事件的所有对象,因此内存消耗会增加,并且有可能会出现与您当前收到的错误相同的错误(但该错误实际上可能与您的单例上下文无关,但很可能不是)。例外情况是,您有两个不同的对象,它们具有由上下文跟踪的相同键标识符 - 这是不允许的。存储库和上下文不使用单例 uow,而是使用单例工厂,并且每次甚至从工厂请求新的实例。在时间事件处理结束时释放上下文。
InSingletonScope
will create singleton context = one context for the whole lifetime of your service. It is very bad solution. Because context holds all objects from all previous time events its memory consumption grows and there are possibilities to get errors as the one you are receiving at the moment (but the error really can be unrelated to your singleton context but most likely it is not). The exception says that you have two different objects with the same key identifier tracked by the context - that is not allowed.Instead of using singleton uow, repository and context use singleton factory and in each time even request new fresh instances from the factory. Dispose context at the end of the time event processing.