2009-07-28 3 views

Antwort

10

ich dieses Problem heute ein wenig untersucht und kommen mit der folgenden Lösung auf Basis von wenigen Quellen Die Idee. ist eine Basisklasse für den Tabellenadapter zu erben, die das Timeout für alle Befehle im Tabellenadapter erhöht, ohne zu viel vorhandenen Code neu schreiben zu müssen.Es muss Reflektion verwendet werden, da die generierten Tabellenadapter nichts Brauchbares erben Stellt eine öffentliche Funktion zum Ändern der Zeitüberschreitung bereit, wenn Sie löschen möchten, was ich im Konstruktor verwendet habe, und verwenden Sie diese Funktion.

1

Angenommen, Ihr Datensatz heißt MySET.
Es gibt eine Tabelle namens MyTable

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

-1 Dies wird nicht funktionieren, da ein stark typisiertes 'TableAdapter' die Eigenschaft' Adapter' nicht freigibt, es ist 'privat'. Der einzige Weg abseits der Spiegelung ist also, die partielle Klasse des TableAdapter zu erweitern, um sie öffentlich zu machen. –

2

In einigen Fällen Sie keine Mitglieder wie Adapter in Ihrer Klasse zugreifen können, da sie als privaten der Klasse definiert sind.

Glücklicherweise wird der Assistent partielle Klassen generieren, was bedeutet, dass Sie sie erweitern können. Wie in [this thread by Piebald] [1] beschrieben, können Sie eine eigene Eigenschaft schreiben, um die Zeitüberschreitung für select-Befehle zu setzen.

Im Allgemeinen würden Sie dies tun:

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

Bitte beachte, dass ich habe nicht wirklich das selbst ausprobiert, aber es scheint wie eine tragfähige Lösung.

+0

Danke! Ich konnte das nicht für mich erledigen, weil _commandCollection null war. Ich habe ein paar Updates gemacht und das als eine andere Antwort gepostet. –

9

Mit ein paar kleinen Änderungen funktioniert die Idee von csl super.

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

es zu nutzen, stellen nur this.FooTableAdapter.CommandTimeout = 60; irgendwo vor der this.FooTableAdapter.Fill();


Wenn Sie auf eine Menge von Tischadapter den Timeout ändern müssen, können Sie eine generische Erweiterungsmethode schaffen könnte und haben Reflektion verwenden das Timeout zu ändern.

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

Verbrauch:

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

Dies ist ein wenig langsamer. Und es besteht die Möglichkeit eines Fehlers, wenn Sie ihn für den falschen Objekttyp verwenden. (Soweit ich weiß, gibt es keine "TableAdapter" -Klasse, auf die Sie beschränken könnten.)

0

Wenn Sie eine partielle Klasse verwenden, haben Sie den richtigen Namespace. Wahrscheinlich [Ihr Datensatz Name] + „Tableadapters. Beispiel:

Namespace MyProject.DataSet1TableAdapters

4

Ich hatte ein paar Probleme mit der Verwendung von Mitchell Gilmans Lösung, die ich schließlich umgehen konnte.

Zuerst musste ich sicherstellen, dass der richtige Namespace verwendet wurde. Es dauerte eine Weile, bis ich herausfand, dass die Designer-Datei für den xsd-Datensatz tatsächlich zwei Namespaces enthält, einen für den Datensatz im Allgemeinen und einen für die Tabellenadapter. Als erstes ist zu beachten, dass der Namespace für den Tabellenadapter verwendet werden sollte, nicht für den Datensatz im Allgemeinen.

Zweitens wird die Befehlssammlung möglicherweise nicht immer initialisiert, wenn der Zeitüberschreitungsbefehl zum ersten Mal verwendet wird. Um dies zu umgehen, habe ich den InitCommandCollection-Befehl aufgerufen, wenn dies der Fall war.

So ist die angepasste Lösung, die ich verwendet wurde, war

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

Hoffnung, dass die Menschen nützlich ist!

0

Sie können den Ordner Eigenschaften öffnen, Settings.settings öffnen und die Eigenschaft Timeout Ihrer Verbindungszeichenfolge ändern.

0

Ich mag das; Klicken Sie mit der rechten Maustaste auf Fill() oder GetX() und klicken Sie im Menü auf Goto Defination.

Sie sehen den Quellcode von DATATABLE. Und finde ;

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

Befehlszeile aus Ihrer DataAdapter-Klasse. Und ändern Sie das Private in die Öffentlichkeit.

Jetzt können Sie auf die _commandCollection zugreifen und Sie können alle Attribute ändern.

Aber seien Sie vorsichtig, wenn Sie ein eingereichtes Formular DESIGNER hinzufügen oder ändern, die Öffentlichkeit wird wieder privat durch autogenerate System sein.

Und auch, wenn Sie Funktion Füllen oder Get rufen beenden Sie zurücksetzen müssen _commandColleciton Aufruf dieser Funktion (InitCommandCollection())

public void InitCommandCollection() {} 

Diese Funktion wird durch Autogen auch privat ist, müssen Sie auch für die öffentliche ändern!

Beispiel:

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

Anruf ChangeTimeout Funktion durch die Tableadapter und Zeit in Sekunden, bereitstellt.

this.ChangeTimeout(this.taTest, 500); 

Funktion:

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

Was ist Interaktion? –

0

Hier einige Beispiel-Code von 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 

Wenn es darum geht, eine lange Abfrage zu rufen, rufen Sie einfach die SetCommandTimeOut Verfahren vor der Abfrage:

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) 
0

Dieses jetzt ein bisschen alt ist und diese Lösung vermuten, ist nicht relevant jeder, aber ich habe AniPol's Lösung endete mit der Object Kontrolle außer Kraft zu setzen, wie folgt:

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

auf den bereits sehr nützlichen Antworten für Tableadapter Erweiterung, die helpe D ich viel, ich hatte auch die Notwendigkeit, den tatsächlichen Timeout-Wert auszulesen. Also:

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

     } 
    } 

} 
0

Es scheint eine bequemere Möglichkeit, dies zu tun. Hier ist eine kurze Zusammenfassung dessen, was ich gefunden habe.

Angenommen, ich füge meiner Lösung ein (Klassenbibliothek) Projekt namens MyDB hinzu. In dieses Projekt füge ich ein DataSet namens "Data" hinzu. Und in diesen Datensatz ziehe ich eine Tabelle namens "X".

Was ich auf der Designoberfläche bekomme, ist ein Objekt, das zeigt, dass ich ein Objekt namens "XTableAdapter" habe.

Ich öffne jetzt den generierten Code, Data.Designer.cs, und suche nach XTableAdapter. Wenn ich es finde, merke ich, dass es in Namespace MyDB.DataTableAdapters enthalten ist - das ist nur eine Verkettung des Namens des Projekts, "MyDB", der Name des DataSet, "Data" und "TableAdapters".

Mit dem in der Hand, gehe ich jetzt zurück in die Klassenbibliothek, noch immer Class1.cs (die ich für jetzt ignorieren werde).

Ich ändere seinen Namespace von MyDB zu MyDB.DataTableAdapters.

using System.Data.SqlClient; 

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

sein könnte Die Aufrufsequenz kaum deutlicher:

ich die Klassendeklaration öffentliche Teilklasse XTableAdapter, und machen es so aussehen ändern

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

Weniger Durcheinander, weniger Aufwand, weniger Reflektion (naja, keine), weniger Füllung.