なぜ私のDBProviderFactoryはSQLClientFactoryとは異なって機能するのですか?
-
11-10-2019 - |
質問
カスタムを実装しました 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プロファイラーを必要とせずに)。これはうまくいきましたが、これを実装した後、次のことを例外としました 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
@があるかどうかに同意します。
ストアドプロシージャは「@」のサインなしではまだ機能します。幸いなことに、パラメーターコレクションのこの直接操作はあまり行いませんが、そもそもなぜこれが起こるのか知りたいです。
助けてくれてありがとう。
解決
さらに掘り出した後、私は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 "@";
}
}
}