我使用DBContext.
Database.sqlQuery< entity>从我的C#代码库执行存储过程.
它工作正常,但我想知道为什么它正在执行如下的过程:
- exec sp_executesql N'EXEC GetCaseList @CaseStage',N'@CaseStage int',@CaseStage=9
而不是
- EXEC GetCaseList @CaseStage = 9
有没有什么办法,我的所有程序从这个c#执行
EXEC GetCaseList @CaseStage = 9而不是exec sp_executesql N’EXEC GetCaseList @ CaseStage’,N’@ CaseStage int’,@ CaseStage = 9?
如何使sql Server Profiler将过程名称视为对象而不是SP_EXECUTEsql?
注意:由于我以表格格式通过sql Server Profiler保存跟踪数据,因此我希望以c#为EXEC GetCaseList @CaseStage = 9执行过程.而在ObjectName列中,它将对象作为对象而不是过程名称(GetCaseList)显示为sp_executesql.我只能从c#代码进行更改.
解决方法
问题是,大多数EF执行的数据库调用使用
DbCommand
与
CommadType
文本,因此虽然sqlServer识别SP调用,它通过sp_executesql执行它们作为文本.
要获得所需的行为,应按以下方式设置命令:
- DbCommand command = ...;
- command.CommandText = "StoredProcedureName";
- command.CommandType = CommadType.StoredProcedure;
不幸的是,EF不提供指定命令类型的标准方式.我建议的解决方案是基于:
>自定义SP使用CallPrefix StoredProcedureName调用sql语法,以便不会干扰常规调用
> EF命令interception删除前缀,并在执行命令前更改命令类型.
这是实现:
- using System.Data;
- using System.Data.Common;
- using System.Data.Entity.Infrastructure.Interception;
- public static class Sp
- {
- public const string CallPrefix = "CallSP ";
- public static string Call(string name) { return CallPrefix + name; }
- public class CallInterceptor : DbCommandInterceptor
- {
- public static void Install()
- {
- DbInterception.Remove(Instance);
- DbInterception.Add(Instance);
- }
- public static readonly CallInterceptor Instance = new CallInterceptor();
- private CallInterceptor() { }
- static void Process(DbCommand command)
- {
- if (command.CommandType == CommandType.Text && command.CommandText.StartsWith(Sp.CallPrefix))
- {
- command.CommandText = command.CommandText.Substring(Sp.CallPrefix.Length);
- command.CommandType = CommandType.StoredProcedure;
- }
- }
- public override void ReaderExecuting(DbCommand command,DbCommandInterceptionContext<DbDataReader> interceptionContext)
- {
- Process(command);
- base.ReaderExecuting(command,interceptionContext);
- }
- }
- }
所有你需要的是将上面的类添加到你的项目中,调用Sp.CallInterceptor.Install()一次,例如在你的DbContext静态构造函数中:
- public class YourDbContext : DbContext
- {
- static YourDbContext()
- {
- Sp.CallInterceptor.Install();
- }
- // ...
- }
然后更改您的SP呼叫(使用您的示例):
从:
至:
- return DataContext.Database.sqlQuery<CaseList>(Sp.Call("GetCaseList"),paramList.CaseStageID)).ToList();
这将生成(对于paramList.CaseStageID == 9):
- EXEC GetCaseList @CaseStage = 9