Подтвердить что ты не робот

Как изменить время ожидания команды адаптера таблицы

Я использую Visual Studio 2008 с С#.

У меня есть файл .xsd, и у него есть адаптер таблицы. Я хочу изменить тайм-аут команды адаптера таблицы.

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

4b9b3361

Ответ 1

Я сегодня немного изучил этот вопрос и придумал следующее решение, основанное на нескольких источниках. Идея состоит в том, чтобы создать базовый класс для адаптера таблицы, который наследует, что увеличивает тайм-аут для всех команд в адаптере таблицы, не переписывая слишком много существующего кода. Он должен использовать отражение, поскольку созданные адаптеры таблицы не наследуют ничего полезного. Он предоставляет публичную функцию для изменения таймаута, если вы хотите удалить то, что я использовал в конструкторе, и использовать его.

using System;
using System.Data.SqlClient;
using System.Reflection;

namespace CSP
{
    public class TableAdapterBase : System.ComponentModel.Component
    {
        public TableAdapterBase()
        {
            SetCommandTimeout(GetConnection().ConnectionTimeout);
        }

        public void SetCommandTimeout(int Timeout)
        {
            foreach (var c in SelectCommand())
                c.CommandTimeout = Timeout;
        }

        private System.Data.SqlClient.SqlConnection GetConnection()
        {
            return GetProperty("Connection") as System.Data.SqlClient.SqlConnection;
        }

        private SqlCommand[] SelectCommand()
        {
            return GetProperty("CommandCollection") as SqlCommand[];
        }

        private Object GetProperty(String s)
        {
            return this.GetType().GetProperty(s, BindingFlags.NonPublic | BindingFlags.GetProperty | BindingFlags.Instance).GetValue(this, null);
        }
    }
}

Ответ 2

С небольшими изменениями идея csl отлично работает.

partial class FooTableAdapter
{
  /**
   * <summary>
   * Set timeout in seconds for Select statements.
   * </summary>
   */
  public int SelectCommandTimeout
  {
    set
    {
            for (int i = 0; i < this.CommandCollection.Length; i++)
                if (this.CommandCollection[i] != null)
                 this.CommandCollection[i].CommandTimeout = value;
    }
  }
}

Чтобы использовать его, просто установите this.FooTableAdapter.CommandTimeout = 60; где-то перед этим .FooTableAdapter.Fill();


Если вам нужно изменить таймаут на множестве адаптеров таблицы, вы можете создать универсальный метод расширения и использовать его для изменения тайм-аута.

/// <summary>
/// Set the Select command timeout for a Table Adapter
/// </summary>
public static void TableAdapterCommandTimeout<T>(this T TableAdapter, int CommandTimeout) where T : global::System.ComponentModel.Component
{                
    foreach (var c in typeof(T).GetProperty("CommandCollection", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetProperty | System.Reflection.BindingFlags.Instance).GetValue(TableAdapter, null) as System.Data.SqlClient.SqlCommand[])
        c.CommandTimeout = CommandTimeout;
}

Использование:

this.FooTableAdapter.TableAdapterCommandTimeout(60);
this.FooTableAdapter.Fill(...);

Это немного медленнее. И есть вероятность ошибки, если вы используете ее для неправильного типа объекта. (Насколько я знаю, нет класса "TableAdapter", который вы могли бы ограничить.)

Ответ 3

У меня было несколько проблем с использованием решения Mitchell Gilman, которое я в конечном итоге смог решить.

Прежде всего, мне нужно было убедиться, что вы используете правильное пространство имен. Мне потребовалось некоторое время, чтобы выяснить, что файл Designer для набора данных xsd фактически содержит два пространства имен: один для набора данных вообще и один для адаптеров таблицы. Поэтому следует обратить внимание на то, что необходимо использовать пространство имен для адаптера таблицы, а не для набора данных вообще.

Во-вторых, команда commandcollection не всегда может быть инициализирована, когда команда таймаута используется в первый раз. Чтобы обойти это, я вызвал команду InitCommandCollection, если это было так.

Итак, адаптированное решение, которое я использовал, было

namespace xxx.xxxTableAdapters

partial class FooTableAdapter
{
  /**
   * <summary>
   * Set timeout in seconds for Select statements.
   * </summary>
   */
  public int SelectCommandTimeout
  {
    set
    {
        if (this.CommandCollection == null)
                this.InitCommandCollection();

        for (int i = 0; i < this.CommandCollection.Length; i++)
            if (this.CommandCollection[i] != null)
             this.CommandCollection[i].CommandTimeout = value;
    }
  }
}

Надеюсь, что это поможет людям!

Ответ 4

В некоторых случаях вы не можете получить доступ к таким членам, как Adapter в своем классе, поскольку они определены как закрытые для класса.

К счастью, мастер будет генерировать частичные классы, что означает, что вы можете их расширить. Как описано в [этой теме Piebald] [1], вы можете написать свое собственное свойство, чтобы установить тайм-аут на команды select.

Как правило, вы сделали бы это:

partial class FooTableAdapter
{
  /**
   * <summary>
   * Set timeout in seconds for Select statements.
   * </summary>
   */
  public int SelectCommandTimeout
  {
    set
    {
      for ( int n=0; n < _commandCollection.Length; ++n )
        if ( _commandCollection[n] != null )
          ((System.Data.SqlClient.SqlCommand)_commandCollection[n])
            .commandTimeout = value;
    }
  }
}

Заметьте, что я на самом деле не пробовал это сам, но это похоже на жизнеспособное решение.

Ответ 5

Скажите, что ваш набор данных называется MySET.
Существует одна таблица под названием MyTable

MySETTableAdapters.MyTableTableAdapter fAdapter = 
   new MySETTableAdapters.MyTableTableAdapter();
fAdapter.Adapter.SelectCommand.CommandTimeout = <fill inyour value here>;

Ответ 6

Вызов функции ChangeTimeout, предоставляя TableAdapter и Time в секундах.

this.ChangeTimeout(this.taTest, 500);

Функция:

 private void ChangeTimeout(Component component, int timeout)
{
    if (!component.GetType().FullName.Contains("TableAdapter")) { 
        return;
    }

    PropertyInfo adapterProp = component.GetType().GetProperty("CommandCollection", BindingFlags.NonPublic | BindingFlags.GetProperty | BindingFlags.Instance);
    if (adapterProp == null) {
        return;
    }

    SqlCommand[] command = adapterProp.GetValue(component, null) as SqlCommand[];

    if (command == null) {
        return;
    }

    Interaction.command(0).CommandTimeout = timeout;
}

Ответ 7

Если вы используете частичный класс, сделайте правильное пространство имен. Вероятно, [ваше имя набора данных] + "TableAdapters". Пример:

namespace MyProject.DataSet1TableAdapters

Ответ 8

Вы можете открыть папку "Свойства", открыть "Настройки" и изменить свойство "Тайм-аут" вашей строки подключения.

Ответ 9

Мне нравится это; Щелкните правой кнопкой мыши Fill() или GetX() и выберите Goto Defination в меню.

Вы увидите исходный код DATATABLE. И найдите

private global::System.Data.SqlClient.SqlCommand[] _commandCollection;

из вашего класса dataadapter. И измените конфиденциальность на общественность.

Теперь вы можете получить доступ к _commandCollection, и вы можете изменить все атрибуты.

Но будьте осторожны при добавлении или изменении любой поданной формы DESIGNER, публика будет снова закрыта системой автогенерации.

А также, когда вы закончите вызов Fill или Get Function, вы должны reset _commandColleciton вызвать эту функцию (InitCommandCollection())

 public void InitCommandCollection() {}

Эта функция также является частной с помощью автогена, вы также должны перейти на публикацию.

Пример:

dsIslemlerTableAdapters.tblIslemlerTableAdapter _t = new dsIslemlerTableAdapters.tblIslemlerTableAdapter();

dsIslemler.tblIslemlerDataTable _m = new dsIslemler.tblIslemlerDataTable();

_t._commandCollection[0].CommandText = "Select * From tblIslemler Where IslemTarihi>='' And IslemTarihi<=''";

_m = _t.GetData();

_t.InitCommandCollection();

Ответ 10

Вот пример кода из MSDN, используя VB.NET:

Imports System.Data.SqlClient
Namespace MyDataSetTableAdapters
    Partial Class CustomersTableAdapter
        Public Sub SetCommandTimeOut(ByVal timeOut As Integer)
            For Each command As SqlCommand In Me.CommandCollection
                command.CommandTimeout = timeOut
            Next
        End Sub
    End Class
End Namespace

Когда придет время для вызова длинного запроса, просто вызовите метод SetCommandTimeOut перед запросом:

Dim ds As New MyDataSet
Dim customersTA As New MyDataSetTableAdapters.CustomersTableAdapter
' Increase time-out to 60 seconds
customersTA.SetCommandTimeOut(60000)
' Do the slow query
customersTA.FillSlowQuery(ds.Customers)

Ответ 11

Это немного устарело и подозревает, что это решение не относится ко всем, но я решил использовать решение AniPol для переопределения элемента управления ObjectDataSource следующим образом:

public class MyObjectDataSource : ObjectDataSource
{
    public MyObjectDataSource()
    {
        this.ObjectCreated += this.MyObjectDataSource_ObjectCreated;
    }

    private void MyObjectDataSource_ObjectCreated(object sender, ObjectDataSourceEventArgs e)
    {
        var objectDataSourceView = sender as ObjectDataSourceView;
        if (objectDataSourceView != null && objectDataSourceView.TypeName.EndsWith("TableAdapter"))
        {
            var adapter = e.ObjectInstance;

            PropertyInfo adapterProp = adapter.GetType()
                .GetProperty(
                    "CommandCollection",
                    BindingFlags.NonPublic | BindingFlags.GetProperty | BindingFlags.Instance);
            if (adapterProp == null)
            {
                return;
            }

            SqlCommand[] commandCollection = adapterProp.GetValue(adapter, null) as SqlCommand[];

            if (commandCollection == null)
            {
                return;
            }

            foreach (System.Data.SqlClient.SqlCommand cmd in commandCollection)
            {
                cmd.CommandTimeout = 120;
            }
        }
    }
}

Ответ 12

Расширяя уже очень полезные ответы на таблицы, которые мне очень помогли, мне также нужно было узнать фактическое значение тайм-аута. Таким образом:

namespace XTrans.XferTableAdapters
{

    public partial class FooTableAdapter
    {
        int? _timeout = null;

        ///<summary>
        ///Get or set the current timeout in seconds for Select statements.
        ///</summary>
        public int CurrentCommandTimeout
        {
            get
            {
                int timeout = 0;

                if (_timeout != null)
                {
                    timeout = (int)_timeout;
                }
                else
                {
                    for (int i = 0; i < this.CommandCollection.Length; i++)
                        if (this.CommandCollection[i] != null)
                            timeout = this.CommandCollection[i].CommandTimeout;
                }
                return timeout;
            }

            set
            {
                if (this.CommandCollection == null)
                    this.InitCommandCollection();

                for (int i = 0; i < this.CommandCollection.Length; i++)
                    if (this.CommandCollection[i] != null)
                    {
                        this.CommandCollection[i].CommandTimeout = value;
                        _timeout = value;
                    }
            }

        }
    }

}

Ответ 13

Кажется, есть более удобный способ сделать это. Вот краткое описание того, что я нашел.

Скажем, я добавляю к моему решению проект (класс библиотеки) MyDB. В этот проект я добавляю DataSet под названием "Данные". И в этот набор данных я перетащил таблицу под названием "X".

То, что я получаю на поверхности дизайна, является объектом, который показывает, что у меня есть объект под названием "XTableAdapter".

Теперь я открываю сгенерированный код Data.Designer.cs и ищу XTableAdapter. Когда я нахожу это, я отмечаю, что он содержится в пространстве имен MyDB.DataTableAdapters - это просто конкатенация имени проекта, "MyDB", имя DataSet, "Data" и "TableAdapters".

С этим я снова вернусь в библиотеку классов, все еще названный Class1.cs(на который я сейчас проигнорирую).

Я изменяю свое пространство имен от MyDB до MyDB.DataTableAdapters.

Я изменяю объявление класса на открытый частичный класс XTableAdapter, и сделайте так:

using System.Data.SqlClient;

namespace MyDB.DataTableAdapters
{
    public partial class XTableAdapter
    {
        public void SetTimeout(int seconds)
        {
            foreach (SqlCommand cmd in CommandCollection)
            {
                cmd.CommandTimeout = seconds;
            }
        }
    }
}

Вызывающая последовательность вряд ли может быть более ясной:

int TwoMinutes = 120;    
XTableAdapter.SetTimeout(TwoMinutes);

Меньше мусс, меньше суеты, меньше отражения (ну, нет), меньше заполняется.

Ответ 14

Если вы перейдете к [имя DataSet].Designer.cs, который является файлом, добавленным в файл набора данных в решении, а затем выполните поиск:

 private void InitCommandCollection();

Это функция, которую вы должны иметь возможность устанавливать свойства для функций, определенных в адаптере таблицы.

Первая строка в этой функции -

this._commandCollection = new global::System.Data.IDbCommand[<number of function defined in a table adapater>];

а затем в следующей строке для каждой из этих функций вы можете установить

((global::System.Data.SqlClient.SqlCommand)(this._commandCollection[<index>])).CommandTimeout = 0;

который 0 означает отсутствие ограничений, и функция не остановится из-за истечения времени ожидания, а также может быть установлена на 10, 20, 30 или 1000 и т.д.