1

我正在尝试使用开箱即用的 ServiceStack 身份验证插件以及 RavenDB 和 RavenUserAuthRepository 包。

应用主机

var store = new DocumentStore()
        {
            ConnectionStringName = "ServiceStackAuthSample"
        }
            .Initialize();

        IndexCreation.CreateIndexes(typeof(RavenUserAuthRepository).Assembly, store);

        container.Register(store);
        var session = container.Resolve<IDocumentStore>().OpenSession();
        container.Register(p => session).ReusedWithin(ReuseScope.Request);

        container.Register<IUserAuthRepository>(p => new RavenUserAuthRepository(p.Resolve<IDocumentStore>(), p.Resolve<IDocumentSession>()));

通过 Facebook、GoogleOAuth、Twitter 进行的第一次身份验证尝试按预期工作。但是,如果我尝试重新进行身份验证,RavenDB 似乎不喜欢它,我得到以下信息:

错误 CodeNonUniqueObjectExceptionmessageAttempted to associate a different object with id 'UserAuths/1'.stack Trace[Auth: 10/21/2013 6:51:04 PM]: [REQUEST: {provider:facebook}] Raven.Client.Exceptions.NonUniqueObjectException:尝试将不同的对象与 id 'UserAuths/1' 相关联。在 Raven.Client.Document.InMemoryDocumentSessionOperations.AssertNoNonUniqueInstance(Object entity, String id) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\InMemoryDocumentSessionOperations.cs:Raven.Client.Document.InMemoryDocumentSessionOperations 的第 778 行。 StoreInternal(Object entity, Etag etag, String id, Boolean forceConcurrencyCheck) 在 c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\InMemoryDocumentSessionOperations.cs:Raven.Client.Document.InMemoryDocumentSessionOperations 的第 670 行。2 authInfo) at ServiceStack.ServiceInterface.Auth.FacebookAuthProvider.Authenticate(IServiceBase authService, IAuthSession session, Auth request) at ServiceStack.ServiceInterface.Auth.AuthService.Authenticate(Auth request, String provider, IAuthSession session, IAuthProvider oAuthConfig) at ServiceStack.ServiceInterface.Auth.AuthService.Post(Auth request) at lambda_method(Closure , Object , Object ) at ServiceStack.ServiceHost.ServiceRunner1.Execute(IRequestContext requestContext, Object instance, TRequest request)

RavenDB 搜索告诉我这可能与我的会话有关,但我不确定我在这里做错了什么。这可能是我对如何在 ServiceStack 中管理 RavenDB 会话的理解。

更新

事实证明,ServiceStack.AuthenticationRavenDb.RavenUserAuthRepository::GetUserAuth方法的 v3 分支中存在错误。当所有其他方法都使用由构造函数注入的私有 IDocumentSession 成员时,GetUserAuth 正在创建一个全新的 IDocumentSession 实例。

private readonly IDocumentStore _documentStore;

public RavenUserAuthRepository(IDocumentStore documentStore,IDocumentSession session)
{
    _documentStore = documentStore;
    _session = session;
}

老的

public UserAuth GetUserAuth(string userAuthId)
{
    using (var session = documentStore.OpenSession())
    {
        int intAuthId;
        return int.TryParse(userAuthId, out intAuthId) 
            ? session.Load<UserAuth>(intAuthId) 
            : session.Load<UserAuth>(userAuthId);
    }
}

固定的

public UserAuth GetUserAuth(string userAuthId)
{
    using (_session)
    {
        int intAuthId;
        return int.TryParse(userAuthId, out intAuthId) 
            ? _session.Load<UserAuth>(intAuthId) 
            : _session.Load<UserAuth>(userAuthId);
    }
}

这导致CreateOrMergeAuthSession使用一个会话实例(通过 GetUserAuth)获取 UserAuth,然后使用私有会话成员保存 UserAuth,从而导致冲突。

谢谢你的提示,大卫!

4

1 回答 1

1

我不熟悉您在此处显示的 ServiceStack DI API,但在我看来,您正在创建和注册一个 DocumentStore(这很好),但随后还创建了一个 IDocumentSession 并仅注册了该实例。每个请求都应该有一个唯一的 IDocumentSession 实例,因此需要将容器配置为每个请求都会调用 DocumentStore 的 OpenSession 方法。

于 2013-10-23T13:19:22.070 回答