4

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);
}

これを行ったのは、コマンドが作成されたときと、すべての SqlCalls のログが終了したときを追跡できるようにするためSqlDataSourceです (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";
}

スローされたエラーは、標準の SqlClientFactory で機能したにもかかわらず、SqlParameter "@x_id" が存在しないというものでした。デバッガーを使用すると、コレクションに 1 つのパラメーターがあり、x_idデフォルトプロバイダーを使用する場合に表示されました。MyProvider@x_id

これには何らかの理由があり、@ を自動的に追加する方法がありますか、それともコード ビハインドを確認しSqlDataSource、@ があるかどうかに同意する必要があります。
ストアド プロシージャは '@' 記号がなくても機能します。幸いなことに、私はこのように Parameters コレクションを直接操作することはあまりありませんが、そもそもなぜこれが起こるのか知りたいです。

助けてくれてありがとう。

4

1 に答える 1

1

さらに掘り下げた後、私は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 "@";
        }
    }

}
于 2010-12-20T20:52:00.610 に答える