簡體   English   中英

實體框架連接池:如何將UserId注入SQL Server session_context?

[英]Entity Framework connection pooling: how to inject UserId into SQL Servers session_context?

我正在開發一個帶有SQL Server的多用戶ASP.Net Web應用程序(在開發人員計算機上使用v2016,在Azure上運行生產)。 在我的應用程序中,我使用EF-6與單個技術用戶連接到數據庫。 連接池處於活動狀態。

為了在此應用程序中進行審計,我想將當前UserId添加到數據庫的每個表的列中(我還想利用UserId來獲取更多內容,但這不會給我的討論增加任何價值)。

由於我不想在我的應用程序的每個LINQ語句中傳遞UserId,我認為利用SQL Server session_context功能會很棒(如下所述: https//lennilobel.wordpress.com/2016/02/29 / sharing-state-in-sql-server-2016-with-session_context / )並通過在應用程序的運行時將userId設置為session_context變量來使數據庫具有狀態感知能力。

在這樣做之后,我能夠通過我的小型數據庫函數GetUserId(從我的角度來看這是一個非常強大的解決方案)在我的表的用戶列的DEFAULT值中使用此session_context變量。 功能如下:

CREATE FUNCTION [dbo].[GetUserId] ()
RETURNS INT
AS
BEGIN
    -- -1 is means "unknown user" (e.g. for transactions executed via SQL Mgmt Studio)
    RETURN COALESCE(CAST(SESSION_CONTEXT(N'UserId') AS INT), -1)
END

現在來了我不確定的事情:

在Entity Framework(或一般的ADO.Net)中注入session_context變量的最佳點在哪里?

目前,我覆蓋了DbContextSaveChanges()方法,並在調用基類SaveChanges之前執行存儲過程:

    public override int SaveChanges()
    {
        SetUserIdContext();
        return base.SaveChanges();
    }

    private void SetUserId()
    {
        this.Database.OpenConnection();

        //Set the user context
        using (var cmd = this.Database.GetDbConnection().CreateCommand())
        {
            var parm = cmd.CreateParameter();
            parm.ParameterName = "@userId";
            parm.Value = this.UserId;

            cmd.CommandText = "SetUserId";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;
            cmd.Parameters.Add(parm);

            cmd.ExecuteNonQuery();
        };
    }

目前,這種方法有效,但絕對不是最好的方法。 我想我可能會以某種方式覆蓋構造函數,但我不確定如何正確地執行此操作。 (另外,因為我不想停用連接池,所以覆蓋連接open命令似乎也是錯誤的)

有沒有人更好地了解我應該如何或在哪里注入我的存儲過程調用,以便我可以確保使用我的應用程序的用戶的狀態總是正確的?

Ps:為了完整性的利益,這里是我調用設置UserId的存儲過程:

CREATE PROCEDURE [dbo].[SetUserId]
    @userId INT
AS
BEGIN
    SET NOCOUNT ON;

    EXEC sp_set_session_context 'UserId', @userId; 
END

非常感謝您對此的想法!

干杯羅蘭

在DbContext構造函數中打開連接並在那里設置UserId。 除非您將DbContext保持活動很長時間(在ASP.NET應用程序中永遠不應該這樣做),否則連接池不會受到太大影響。

我怎樣才能保證我在構造函數中打開的連接(以及傳遞給UserId的連接)仍然與稍后在我的業務邏輯中調用SaveChanges時使用的連接相同?

如果在構造函數中顯式打開連接(或打開並傳遞給構造函數),則DbContext將不會關閉並重新打開它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM