c# - 为什么我的 DbProviderFactory 的执行方式与 SqlClientFactory 不同?

标签 c# .net ado.net sqldatasource dbproviderfactories

我实现了一个自定义的 DbProviderFactory,它返回了 SqlX 类型,除了我将以下逻辑添加到 CreateCommand

public override DbCommand CreateCommand()
{
    var cmd = new SqlCommand();
    if (CommandCreated != null)
        CommandCreated(cmd, EventArgs.Empty);
    cmd.StatementCompleted += cmd_StatementCompleted;
    return cmd;
}

void cmd_StatementCompleted(object sender, StatementCompletedEventArgs e)
{
    if (StatementCompleted != null)
        StatementCompleted(sender, e);
}

我这样做是为了在 SqlDataSource 创建命令时进行跟踪,然后在它完成记录所有 SqlCalls 时进行跟踪(无需启动 Sql Profiler)。这行得通,但是在我实现它之后,我得到了以下 SqlDataSource

的异常
<asp:SqlDataSource ProviderName="MyProvider" ID="SqlDataSource1" 
    runat="server" ConnectionString="<%$ ConnectionStrings:default %>"
    SelectCommandType="StoredProcedure"
    SelectCommand="dbo.GetX" 
    OnSelecting="SqlDataSource1_Selecting">
    <SelectParameters>
      <asp:Parameter Name="x_id" Type="Byte"/>
    </SelectParameters>
</asp:SqlDataSource>

这在后面的代码中。

protected void SqlDataSource1_Selecting(object sender, SqlDataSourceCommandEventArgs e)
{
    e.Command.Parameters["@x_id"].Value = "something else";
}

抛出的错误是 SqlParameter“@x_id”不存在,即使它适用于标准 SqlClientFactory。使用调试器时,它显示在使用 MyProvider 时集合 x_id 中有 1 个参数,在使用默认提供程序时显示 @x_id

这有什么原因吗?有什么方法可以自动添加@,还是我应该确保代码隐藏和 SqlDataSource 就是否有 @ 达成一致?或者不是。
存储过程在没有“@”符号的情况下仍然有效,幸运的是我并没有太多地直接操作参数集合,但我首先想知道为什么会发生这种情况。

感谢您的帮助。

最佳答案

深入挖掘后,我在 SqlDataSourceView 的源代码中发现了以下内容

protected virtual string ParameterPrefix
{
  get
  {
    if (!string.IsNullOrEmpty(this._owner.ProviderName) && !string.Equals(this._owner.ProviderName, "System.Data.SqlClient", StringComparison.OrdinalIgnoreCase))
    {
      return string.Empty;
    }
    return "@";
  }
}

因此,当使用您自己的 Provider 时,它与预期的 Provider 名称不匹配,因此它只返回 string.Empty。如果您需要这样做,那么您将不得不继承 SqlDataSource 和 SqlDataSourceView

public class MySqlDataSource : SqlDataSource
{
    protected override SqlDataSourceView CreateDataSourceView(string viewName)
    {
        return new MySqlDataSourceView(this, viewName, this.Context);
    }
}

public class MySqlDataSourceView : SqlDataSourceView
{
    private MySqlDataSource _owner;
    public MySqlDataSourceView(IPSqlDataSource owner, string name, System.Web.HttpContext context)
        : base(owner, name, context)
    {
        _owner = owner;
    }

    protected override string ParameterPrefix
    {
        get
        {
            if (!string.IsNullOrEmpty(this._owner.ProviderName) && !string.Equals(this._owner.ProviderName, "MyProvider", StringComparison.OrdinalIgnoreCase))
            {
                return base.ParameterPrefix;
            }
            return "@";
        }
    }

}

关于c# - 为什么我的 DbProviderFactory 的执行方式与 SqlClientFactory 不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4474774/

相关文章:

c# - 如何在C#中正确使用Performance Counter或Process类来获取当前进程的内存使用情况?

.net - 在Azure Web Api应用程序中引用 native 64位dll

c++ - 使用 Console::WriteLine() 的 Windows char 和 Char 类型和字符串

c# - 目标框架中缺少“WindowsBase”、 'PresentationCore'、 'PresentationFramework'

ado.net - Db命令和参数: Get the actual executed SQL (Parameter values filled in)

entity-framework - vs2010中找不到ADO.NET实体模型浏览器窗口

ado.net - 使用 Microsoft 应用程序 block 进行数据访问时,DataReader.Close() 方法是否关闭连接对象?

c# - Select() 命令的 System.Linq.Dynamic.DynamicExpression.ParseLambda 问题

c# - 如何修改c#,ASP .NET中的请求头

c# - 如何在 C# 中使用 “for” 循环创建动态递增变量