根据RavenDb tutorial,您的应用程序需要一个IDocumentStore 实例(我假设每个数据库)。 IDocumentStore 是线程安全的。它产生IDocumentSession 实例,它们代表RavenDB 中的unit of work,这些是非 线程安全的。因此,您应该不在线程之间共享会话。
如何设置容器以与 RavenDb 一起使用主要取决于应用程序设计。问题是:你想给消费者注入什么? IDocumentStore,还是IDocumentSession?
当您使用IDocumentStore 时,您的注册可能如下所示:
// Composition Root
IDocumentStore store = new DocumentStore
{
ConnectionStringName = "http://localhost:8080"
};
store.Initialize();
container.RegisterSingle<IDocumentStore>(store);
消费者可能看起来像这样:
public class ProcessLocationCommandHandler
: ICommandHandler<ProcessLocationCommand>
{
private readonly IDocumentStore store;
public ProcessLocationCommandHandler(IDocumentStore store)
{
this.store = store;
}
public void Handle(ProcessLocationCommand command)
{
using (var session = this.store.OpenSession())
{
session.Store(command.Location);
session.SaveChanges();
}
}
}
由于IDocumentStore 被注入,消费者自己负责管理会话:创建、保存和处置。这对于小型应用程序非常方便,或者例如在将 RavenDb 数据库隐藏在 repository 后面时,您可以在 repository.Save(entity) 方法中调用 session.SaveChanges()。
但是,我发现这种使用工作单元的方式对于大型应用程序来说是有问题的。因此,您可以做的是将IDocumentSession 注入消费者。在这种情况下,您的注册可能如下所示:
IDocumentStore store = new DocumentStore
{
ConnectionStringName = "http://localhost:8080"
};
store.Initialize();
// Register the IDocumentSession per web request
// (will automatically be disposed when the request ends).
container.RegisterPerWebRequest<IDocumentSession>(
() => store.OpenSession());
请注意,您需要Simple Injector ASP.NET Integration NuGet package(或将SimpleInjector.Integration.Web.dll 包含在您的项目中,默认下载中包含)才能使用RegisterPerWebRequest扩展方法。
现在的问题变成了,在哪里打电话给session.SaveChanges()?
有一个关于根据网络请求注册作品单元的问题,它也解决了关于SaveChanges 的问题。请好好看看这个答案:One DbContext per web request…why?。当您将单词DbContext 替换为IDocumentSession 并将DbContextFactory 替换为IDocumentStore 时,您将能够在RavenDb 的上下文中阅读它。请注意,在使用 RavenDb 时,业务交易或一般交易的概念可能并不那么重要,但老实说我不知道。这是你必须自己找出来的东西。