我们需要为我们的应用程序做同样的事情。正如 Kim 所说,Dev Force 论坛中有很多信息。您可以在此论坛帖子中找到我们所做工作的完整说明,但我将在此处复制重要部分以供参考...
我们的应用程序中有类似的要求。在我们的例子中,每次打开数据库连接时,我们都需要调用自定义存储过程——该过程将“标记”与当前活动用户的连接,因为我们有很多需要知道当前用户的触发器(我们使用context_info 来完成这个“标记”)。
我们能够在EF Provider Wrapper Toolkit的帮助下处理这个问题(现在似乎也在Nuget上)。这基本上可以让您将自己的逻辑注入到各种 ADO.NET 对象中——因此在数据库访问的最低级别。然后,我们制作了 DevForce/EntityFramework 最终使用的自定义 DbConnection 类。它实际上非常简单,并且为我们提供了很多很好的“挂钩”到最低级别的数据库访问,这些都派上了用场。
下面是我们的自定义 DbConnection 类的一些示例代码,显示了您可以完成的各种事情:
/// <summary>
/// Custom implementation of a wrapper to <see cref="DbConnection"/>.
/// Allows custom behavior at the connection level.
/// </summary>
internal class CustomDbConnection : DbConnectionWrapper
{
/// <summary>
/// Opens a database connection with the settings specified by
/// the <see cref="P:System.Data.Common.DbConnection.ConnectionString"/>.
/// </summary>
public override void Open()
{
base.Open();
//After the connection has been opened, do our logic to prep the connection
SetContextInfo();
//...and we do some other stuff not relevant to this discussion
}
/// <summary>
/// Closes the connection to the database. This is the preferred method of closing any open connection.
/// </summary>
/// <exception cref="T:System.Data.Common.DbException">
/// The connection-level error that occurred while opening the connection.
/// </exception>
public override void Close()
{
//Before closing, we do some cleanup with the connection to make sure we leave it clean
// for the next person that might get it....
base.Close();
}
/// <summary>
/// Attempts to set context_info to the current connection if the user is
/// logged in to our application.
/// </summary>
private void SetContextInfo()
{
//See if a user is logged in
var user = Thread.CurrentPrincipal as OurCustomUserType;
//If not, we don't need to do anything - this is probably a very early call in the application
if (user == null)
return;
//Create the ADO.NET command that will call our stored procedure
var cmd = CreateCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "p_prepare_connection_for_use";
//Set the parameters based on the currently logged in user
cmd.CreateParameter("as_session_id", user.SessionID, null, DbType.Guid);
cmd.CreateParameter("ai_user_sid", user.UserID, null, DbType.Int32);
//Run the SP
cmd.ExecuteNonQuery();
}
在 EF6 及更高版本中,可能有一种更简洁的方法来拦截数据库调用......但这种方法多年来一直很好用。