ServiceStack:在InsertFilter和UpdateFilter中访问会话

时间:2016-02-25 13:45:51

标签: c# servicestack ormlite-servicestack

我有一个C#.net应用程序,我正在写一个sql server数据库。 SQL Server表都有常见的记录管理列(DateCreated,DateLastUpdated,CreatedUserId等...),我希望将这些字段的填充抽象为InsertFilter和UpdateFilter。

以下是AppHost配置方法的缩减版本。

public override void Configure(Container container)
{
    ICacheClient CacheClient = new MemoryCacheClient();
    container.Register(CacheClient);

    var connectionString = ConfigurationManager.ConnectionStrings["mydb"].ConnectionString;

    container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(connectionString, SqlServerDialect.Provider));

    container.Register<IUserAuthRepository>(c => new OrmLiteAuthRepository(c.Resolve<IDbConnectionFactory>()));
    var authRepo = (OrmLiteAuthRepository)container.Resolve<IUserAuthRepository>();


    OrmLiteConfig.InsertFilter = (dbCmd, row) =>
    {
        var userSession = SessionFeature.GetOrCreateSession<AuthUserSession>(CacheClient);
        var recordManagementRow = row as IRecordManagement;
        if (recordManagementRow != null)
        {
            recordManagementRow.DateCreated = recordManagementRow.DateLastUpdated = DateTime.UtcNow;
            if (userSession != null)
                recordManagementRow.CreatedUserId = recordManagementRow.LastUpdatedUserId = userSession.Id.ToInt();
        }
    };
}

执行时,我在OrmLiteConfig.InsertFilter委托的第一行得到以下异常。有没有人对如何检索插入数据库的当前用户会话ID有任何更好的想法?

  

ServiceStack.dll中出现'System.NotImplementedException'类型的异常,但未在用户代码中处理

     

其他信息:此AppHost不支持通过Singleton访问当前请求

1 个答案:

答案 0 :(得分:2)

User Session只能在请求的上下文中访问,因为它取决于当前请求的Session Cookies

只有ASP.NET主机才能访问HttpContext.Current单例来访问当前请求。尝试访问HTTP侦听器自身主机中的用户会话而不注入当前HTTP Request时,您将收到此异常,例如:

var userSession = SessionFeature
    .GetOrCreateSession<AuthUserSession>(CacheClient, Request);

我建议不要尝试访问这样的用户会话,而是在IRecordManagement上创建一个扩展方法,填充POCO,类似于InsertFilter正在做的事情,例如:

db.Insert(new Record { ... }.WithAudit(Request.GetSession().UserAuthId));

//Extension Method Example:
public static class RecordManagementExtensions
{
    public static T WithAudit<T>(this T row, string userId) where T : IRecordManagement
    {
        row.UserId = userId;
        row.DateCreated = DateTime.UtcNow;
        return row;
    }
}

虽然我不建议依赖RequestContext单例,但在这种情况下可以使用它来为请求过滤器中的请求设置当前UserId,例如:

GlobalRequestFilters.Add((req, res, requestDto) => {
    RequestContext.Instance.Items["userId"] = req.GetSession().UserAuthId;
});

然后您可以从过滤器访问,例如:

OrmLiteConfig.InsertFilter = (dbCmd, row) => {
    ...
    recordMgt.CreatedUserId = RequestContext.Instance.Items["userId"];
}