2016-02-25 78 views
2

我有一個正在寫入sql server數據庫的C#.net應用程序。 SQL Server表都具有通用的記錄管理列(DateCreated,DateLastUpdated,CreatedUserId等),我希望將這些字段的總體抽象爲InsertFilter和UpdateFilter。ServiceStack:在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插入數據庫?

類型「System.NotImplementedException」的一個例外發生在ServiceStack.dll但在用戶代碼中沒有處理

附加信息:該APPHOST不支持通過一個Singleton

訪問當前請求

回答

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單,你可以用它在這種情況下設置爲當前用戶ID請求過濾器中的請求,例如:

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

,你會那麼可以在使用過濾器來訪問,如:

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

感謝傑米斯,我相信你們已經提供了兩種解決方法 - 通過你的POCO&也擴展方法推薦人羣在這個例子中可以使用RequestFilter來將UserId填充到RequestContext上。我不明白我怎麼可以接受這個建議,你會介意增加一點語法嗎? – Drammy

+0

僅供參考:我已經有了RequestContext解決方案,但我寧願選擇推薦的方法,因爲它對我來說感覺更清潔。 – Drammy

+1

@Drammy我已經更新了擴展方法來傳遞UserSession UserId,因爲這就是你所需要的。擴展方法是爲了使呼叫站點代碼更小(通過檢索ext方法中的UserId),所以這種改變使得它更加明確,但是每個呼叫站點代碼更多。 – mythz