Perché il mio DbProviderFactory performance rispetto a SqlClientFactory?
-
11-10-2019 - |
Domanda
Ho implementato un DbProviderFactory
personalizzato che ha restituito i tipi SqlX tranne ho aggiunto la seguente logica per 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);
}
Ho fatto questo in modo da poter tenere traccia di ogni volta che un SqlDataSource
creato un comando e poi quando è finito per registrare tutte le SqlCalls (senza bisogno di SQL Profiler su). Questo ha funzionato, ma dopo ho realizzato questo ho ottenuto un'eccezione con il seguente 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>
e questo nel codice dietro.
protected void SqlDataSource1_Selecting(object sender, SqlDataSourceCommandEventArgs e)
{
e.Command.Parameters["@x_id"].Value = "something else";
}
L'errore di essere gettato era che lo SqlParameter "@x_id" non esiste, anche se questo ha lavorato con lo SqlClientFactory standard. Quando si utilizza il debugger ha dimostrato che non vi era 1 parametro nel x_id
collezione quando si utilizzano MyProvider
, e @x_id
quando si utilizza il provider predefinito.
C'è qualche motivo per questo e c'è un modo posso ottenere il @ 's aggiunto automaticamente o devo solo assicurarsi che il code-behind e la SqlDataSource
d'accordo su se vi sia un @ oppure no.
La stored procedure funziona ancora senza il segno '@' e per fortuna non faccio questa manipolazione diretta della collezione Parameters molto, ma vorrei sapere perché questo accade, in primo luogo.
Grazie per l'aiuto.
Soluzione
Dopo aver scavato più ho trovato quanto segue nella Fonte di 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 "@";
}
}
e così quando si utilizza il proprio provider non corrisponde il nome del provider previsto e quindi restituisce solo string.Empty. Se hai bisogno di fare questo, allora si dovrà sottoclasse SqlDataSource e 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 "@";
}
}
}