Почему мой DbProviderFactory работает иначе, чем SqlClientFactory? - PullRequest
4 голосов
/ 18 декабря 2010

Я реализовал пользовательский 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.При использовании отладчика он показал, что в коллекции x_id был 1 параметр при использовании MyProvider и @x_id при использовании поставщика по умолчанию.

Есть ли какая-то причина для этого и есть ли способЯ могу автоматически добавить @ или убедиться, что код и SqlDataSource согласны с тем, есть ли @ или нет.
Хранимая процедура по-прежнему работает без знака @ и, к счастью,Я не особо занимаюсь этой прямой манипуляцией с коллекцией параметров, но мне хотелось бы знать, почему это происходит в первую очередь.

Спасибо за помощь.

1 Ответ

1 голос
/ 20 декабря 2010

После копания больше я нашел следующее в 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 "@";
  }
}

и поэтому при использовании вашего собственного провайдера он не соответствует ожидаемому имени провайдера и поэтому просто возвращает 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 "@";
        }
    }

}
...