Come posso cambiare il timeout del comando della scheda di tabella

Sto usando Visual Studio 2008 con C #.

Ho un file .xsd e ha un adattatore da tavolo. Voglio cambiare il timeout del comando dell’adattatore da tavolo.

Grazie per l’aiuto.

    Ho esaminato un po ‘questo problema oggi e ho trovato la seguente soluzione basata su alcune fonti. L’idea è quella di creare una class base per l’ereditarietà della tabella, che aumenta il timeout per tutti i comandi nell’adattatore di tabella senza dover riscrivere troppo codice esistente. Deve usare la riflessione poiché gli adattatori della tabella generati non ereditano nulla di utile. Espone una funzione pubblica per modificare il timeout se si desidera eliminare ciò che ho usato nel costruttore e usarlo.

    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); } } } 

    Con alcune piccole modifiche l’idea di csl funziona alla grande.

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

    Per usarlo, basta impostare this.FooTableAdapter.CommandTimeout = 60; da qualche parte prima di this.FooTableAdapter.Fill ();


    Se è necessario modificare il timeout su molti adattatori di tabella, è ansible creare un metodo di estensione generico e utilizzarlo per riflettere il timeout.

     ///  /// Set the Select command timeout for a Table Adapter ///  public static void TableAdapterCommandTimeout(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; } 

    Uso:

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

    Questo è un po 'più lento. E c'è la possibilità di un errore se lo si utilizza sul tipo di object sbagliato. (Per quanto ne so, non esiste una class "TableAdapter" che potresti limitare a).

    Ho avuto un paio di problemi con l’utilizzo della soluzione di Mitchell Gilman che alla fine sono riuscito a risolvere il problema.

    Prima di tutto, dovevo assicurarmi di usare il giusto spazio dei nomi. Mi ci è voluto un po ‘per capire che il file Designer per il dataset xsd contiene effettivamente due namespace, uno per il set di dati in generale e uno per gli adattatori di tabella. Quindi la prima cosa da notare è che lo spazio dei nomi per l’adattatore da tavolo dovrebbe essere usato, non per il set di dati in generale.

    In secondo luogo, la raccolta dei comandi potrebbe non essere sempre inizializzata quando il comando di timeout viene utilizzato per la prima volta. Per ovviare a questo, ho chiamato il comando InitCommandCollection se fosse il caso.

    Quindi la soluzione adattata che ho usato era

     namespace xxx.xxxTableAdapters partial class FooTableAdapter { /** *  * Set timeout in seconds for Select statements. *  */ 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; } } } 

    Spero che sia utile per le persone!

    In alcuni casi non è ansible accedere ai membri come Adattatore nella class, poiché sono definiti come privati per la class.

    Fortunatamente, la procedura guidata genererà classi parziali, il che significa che è ansible estenderle. Come descritto in [questo thread di Piebald] [1], puoi scrivere la tua proprietà per impostare il timeout su select-commands.

    In generale, dovresti fare questo:

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

    Si noti che in realtà non ho provato questo, ma sembra una soluzione valida.

    Supponiamo che il set di dati si chiami MySET.
    C’è una tabella chiamata MyTable

     MySETTableAdapters.MyTableTableAdapter fAdapter = new MySETTableAdapters.MyTableTableAdapter(); fAdapter.Adapter.SelectCommand.CommandTimeout = ; 

    Chiama la funzione ChangeTimeout fornendo TableAdapter e Time in secondi.

     this.ChangeTimeout(this.taTest, 500); 

    Funzione :

      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; } 

    Se si utilizza una class parziale, si ottiene lo spazio dei nomi corretto. Probabilmente [nome del set di dati] + “TableAdapters”. Esempio:

    namespace MyProject.DataSet1TableAdapters

    È ansible aprire la cartella Proprietà, aprire Settings.settings e modificare la proprietà Timeout della stringa di connessione.

    Ecco alcuni esempi di codice da MSDN , utilizzando 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 

    Quando arriva il momento di chiamare una lunga query, basta chiamare il metodo SetCommandTimeOut prima della query:

     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) 

    Questo è un po ‘vecchio ora e sospetto che questa soluzione non sia rilevante per tutti, ma ho finito per usare la soluzione di AniPol per sovrascrivere il controllo ObjectDataSource come segue:

     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; } } } } 

    Mi piace questo; Fare clic con il tasto destro del mouse su Fill() o GetX() e fare clic su Goto Defination dal menu.

    Vedrai il codice sorgente di DATATABLE. E trova ;

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

    riga di comando dalla class dataadapter. E cambia il privato in pubblico.

    Ora puoi accedere a _commandCollection e puoi modificare tutti gli attributi.

    Ma fai attenzione quando aggiungi o modifichi qualsiasi modulo di archiviazione PROGETTISTA, il pubblico sarà nuovamente privato dal sistema di generazione automatica.

    Inoltre, quando si finisce di chiamare Fill o Get Function, è necessario ripristinare _commandColleciton chiamando questa funzione ( InitCommandCollection() )

      public void InitCommandCollection() {} 

    Anche questa funzione è privata di autogen, devi anche cambiare in pubblico!

    Esempio:

     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(); 

    Ampliando le risposte già molto utili per i tableadapters che mi hanno aiutato molto, ho anche avuto bisogno di leggere il valore attuale del timeout. Così:

     namespace XTrans.XferTableAdapters { public partial class FooTableAdapter { int? _timeout = null; /// ///Get or set the current timeout in seconds for Select statements. /// 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; } } } } } 

    Sembra che ci sia un modo più conveniente per farlo. Ecco un breve riepilogo di ciò che ho trovato.

    Diciamo che aggiungo un progetto (libreria di classi) chiamato MyDB alla mia soluzione. In quel progetto aggiungo un DataSet chiamato “Dati”. E in quel set di dati, trascino un tavolo chiamato “X”.

    Quello che ottengo sulla superficie del design è un object che mostra che ho un object chiamato “XTableAdapter”.

    Ora apro il codice generato, Data.Designer.cs, e cerco XTableAdapter. Quando lo trovo, noto che è contenuto nello spazio dei nomi MyDB.DataTableAdapters – che è solo una concatenazione del nome del progetto, “MyDB”, il nome del DataSet, “Data” e “TableAdapters”.

    Con quello in mano, ora torno alla libreria di classi, ancora chiamata Class1.cs (che ignorerò per ora).

    Cambio il suo spazio dei nomi da MyDB a MyDB.DataTableAdapters.

    Io cambio la dichiarazione della class in XTableAdapter della class pubblica pubblica , e la faccio apparire così:

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

    La sequenza di chiamata potrebbe difficilmente essere più chiara:

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

    Meno muss, meno confusione, meno riflessione (beh, nessuna), meno riempimento.