【发布时间】:2018-10-28 21:13:14
【问题描述】:
客户需要将每次数据更改记录到记录表中,并与进行修改的实际用户一起记录。应用程序使用一个 SQL 用户访问数据库,但我们需要记录“真实”用户 ID。
我们可以在 t-sql 中通过为每个表插入和更新编写触发器并使用 context_info 来存储用户 ID 来做到这一点。我们将用户 ID 传递给存储过程,将用户 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();
错误:查询语法无效。
所以我在这里,坚持在实体框架和 ADO.NET 之间建立一座桥梁。 如果我可以让它工作,我会发布一个概念证明。
【问题讨论】:
-
用户真的希望您使用 EF,然后要求您坚持使用 SQL 2000?
-
有一篇关于审计here的有趣帖子,你怎么看?
-
六年后,我仍然认为这是一个很好的方法。触发器比应用程序级代码更适合审计,这提供了一种在不污染应用程序级代码的情况下将“真实”用户信息获取到数据库层的绝妙方法。
-
这里davecallan.com/passing-userid-delete-trigger-entity-framework/# 使用事务方法来确保使用相同的连接。