使用Entity Framework記錄每個數據更改

entity-framework logging

客戶需要將每個數據更改記錄到與進行修改的實際用戶的日誌記錄表中。應用程序使用一個SQL用戶來訪問數據庫,但我們需要記錄“真實”用戶ID。

我們可以在t-sql中通過為每個表插入和更新編寫觸發器,並使用context_info來存儲用戶ID來完成此操作。我們將用戶標識傳遞給存儲過程,將用戶標識存儲在contextinfo中,觸發器可以使用此信息將日誌行寫入日誌表。

我無法找到使用EF在哪里或如何做類似的地方或方式。所以主要目標是:如果我通過EF對數據進行更改,我想以半自動的方式將確切的數據更改記錄到表中(因此我不想在每個字段之前檢查更改)保存對象)。我們正在使用EntitySQL。

不幸的是,我們必須堅持SQL 2000,因此SQL2008中引入的數據更改捕獲不是一個選項(但也許這對我們來說也不是正確的方法)。

任何想法,鏈接或起點?

[編輯]一些注意事項:通過使用ObjectContext.SavingChanges事件處理程序,我可以得到我可以注入SQL語句來初始化contextinfo的點。但是我不能混合使用EF和標準SQL。所以我可以獲得EntityConnection但我無法使用它執行T-SQL語句。或者我可以獲取EntityConnection的連接字符串並基於它創建一個SqlConnection,但它將是一個不同的連接,因此contextinfo不會影響EF的保存。

我在SavingChanges處理程序中嘗試了以下內容:

testEntities te = (testEntities)sender;
DbConnection dc = te.Connection;
DbCommand dcc = dc.CreateCommand();
dcc.CommandType = CommandType.StoredProcedure;
DbParameter dp = new EntityParameter();
dp.ParameterName = "userid";
dp.Value = textBox1.Text;
dcc.CommandText = "userinit";
dcc.Parameters.Add(dp);
dcc.ExecuteNonQuery();

錯誤:EntityCommand.CommandText的值對StoredProcedure命令無效。與SqlParameter相同而不是EntityParameter:SqlParameter不能使用。

StringBuilder cStr = new StringBuilder("declare @tx char(50); set @tx='");
cStr.Append(textBox1.Text);
cStr.Append("'; declare @m binary(128); set @m = cast(@tx as binary(128)); set context_info @m;");

testEntities te = (testEntities)sender;
DbConnection dc = te.Connection;
DbCommand dcc = dc.CreateCommand();
dcc.CommandType = CommandType.Text;
dcc.CommandText = cStr.ToString();
dcc.ExecuteNonQuery();

錯誤:查詢語法無效。

所以在這裡,我堅持在Entity Framework和ADO.NET之間建立一座橋樑。如果我可以使它工作,我會發布一個概念證明。

一般承認的答案

如何處理Context。 SavingChanges


熱門答案

謝謝你指點我正確的方向。但是,在我的情況下,我還需要在執行select語句時設置上下文信息,因為我查詢使用上下文信息來控制用戶的行級安全性的視圖。

我發現最容易附加到連接的StateChanged事件,只是注意從非打開到打開的更改。然後我調用設置上下文的proc,它每次都有效,即使EF決定重置連接。

private int _contextUserId;

public void SomeMethod()
{
    var db = new MyEntities();
    db.Connection.StateChange += this.Connection_StateChange;
    this._contextUserId = theCurrentUserId;

    // whatever else you want to do
}

private void Connection_StateChange(object sender, StateChangeEventArgs e)
{
    // only do this when we first open the connection
    if (e.OriginalState == ConnectionState.Open ||
        e.CurrentState != ConnectionState.Open)
        return;

    // use the existing open connection to set the context info
    var connection = ((EntityConnection) sender).StoreConnection;
    var command = connection.CreateCommand();
    command.CommandText = "proc_ContextInfoSet";
    command.CommandType = CommandType.StoredProcedure;
    command.Parameters.Add(new SqlParameter("ContextUserID", this._contextUserId));
    command.ExecuteNonQuery();
}


Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因