当CommandType为StoredProcedure时,如何使用IDbCommandInterceptor修改SQL

时间:2016-11-11 19:37:08

标签: c# sql-server entity-framework

我使用的是Entity Framework 6,并希望在对数据进行任何修改之前设置CONTEXT_INFO,因此我的审核触发器可以记录哪些用户进行了修改。看来应该可以使用IDbCommandInterceptor来更改将要执行的CommandText,类似下面的代码。但是如果DbCommand.CommandType == CommandType.StoredProcedure那么它不是这样的,因为它期望CommandText只是过程名称,如果我用它作为前缀,则会抛出错误我的额外SQL。

public class SetContextInterceptor : IDbCommandInterceptor
{

    public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
    {
        command.CommandText = GetSqlForSetContextInfo() + command.CommandText;
    }

     // ... other interface methods similar

    private string GetSqlForSetContextInfo()
    {
        var currentUsername = Thread.CurrentPrincipal != null && Thread.CurrentPrincipal.Identity != null
            ? Thread.CurrentPrincipal.Identity.Name
            : null;

        if (String.IsNullOrEmpty(currentUsername))
        {
            return "";
        }

        return "EXEC usp_setUserContext '" + currentUsername.Replace('\'', ' ') + "'; ";
    }

} 

特别是在这种情况下CommandText中的参数不存在(即CommandText只包含存储过程名称),所以我不想进入做字符串的混乱业务操纵参数。有一种简单的方法来处理这种情况吗?

这里有一些关于用CONTEXT_INFO实现类似事情的其他文章。看起来这个主题有很多变化,但没有达成一致的方式,许多技术都是在EF6之前,所以没有IDbCommandInterceptor选项。

更新

我猜测因为it's not possible to get the 'SQL' that's executed当CommandType = StoredProcedure时,它无法操纵它。我遇到的选项(对于我想设置CONTEXT_INFO的场景)是抓取command.Connection并执行单独的命令来设置CONTEXT_INFO。我不确定它的效果如何,例如如果连接尚未打开,那么我必须自己打开它。

From .NET can I get the full SQL string generated by a SqlCommand object (with SQL Parameters)?

1 个答案:

答案 0 :(得分:0)

根据我上面的更新,我认为这是不可能的。