为什么我的 DbProviderFactory 的性能与 SqlClientFactory 不同?

发布于 2024-10-08 01:14:55 字数 1618 浏览 0 评论 0原文

我实现了一个自定义的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 就是否存在 @ 达成一致。
存储过程在没有“@”符号的情况下仍然可以工作,幸运的是,我对参数集合的直接操作不多,但我想知道为什么会发生这种情况。

感谢您的帮助。

I implemented a custom DbProviderFactory which returned the SqlX types except I added the following logic to 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);
}

I did this so I could track whenever a SqlDataSource created a command and then when it finished to log all SqlCalls (without needing Sql Profiler up). This worked, however after I implemented this I got an exception with the following 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>

and this in the code behind.

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

The error being thrown was that the SqlParameter "@x_id" doesn't exist, even though this worked with the standard SqlClientFactory. When using the debugger it showed that there was 1 parameter in the collection x_id when using MyProvider, and @x_id when using the default provider.

Is there some reason for this and is there some way I can get the @'s added automatically or should I just make sure the code-behind and the SqlDataSource agree on whether there is an @ or not.
The Stored Procedure still works without the '@' sign and luckily I don't do this direct manipulation of the Parameters collection much but I would like to know why this happens in the first place.

Thanks for the help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

五里雾 2024-10-15 01:14:55

经过更多挖掘后,我在 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 "@";
  }
}

,因此当使用您自己的提供程序时,它与预期的提供程序名称不匹配,因此它只返回 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 "@";
        }
    }

}

After digging more I found the following in the Source of 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 "@";
  }
}

and so when using your own Provider it doesn't match the expected Provider name and so it just returns string.Empty. If you need to do this then you will have to subclass SqlDataSource and 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 "@";
        }
    }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文