Why does my DbProviderFactory work differently than SqlClientFactory?

I implemented a custom DbProviderFactory that returned SqlX types, except that 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 that I could track every time SqlDataSource created the command, and then when it finished writing all SqlCalls (without the need to use Sql Profiler). This worked, however after that 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 is in code.

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

The error caused by the fact that SqlParameter "@x_id" does not exist, even if it works with the standard SqlClientFactory. When using the debugger, he showed that when using MyProvider and @x_id when using the default provider, the x_id collection has 1 parameter.

Is there any reason for this, and is there a way in which I can automatically add @, or should I just make sure the code and SqlDataSource agree on whether there is @ or not. The stored procedure still works without the "@" sign, and, fortunately, I do not do this direct manipulation of the parameter collection, but I would like to know why this happens in the first place.

Thanks for the help.

+4
source share
1 answer

After searching many times, I found the following in the SqlDataSourceView source

 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 therefore when using your own provider it does not match the expected provider name, and therefore it just returns string.Empty. If you need to do this, 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 "@"; } } } 
+1
source

Source: https://habr.com/ru/post/1332550/


All Articles