如何更改表适配器的命令超时

我正在使用Visual Studio 2008和C#。

我有一个.xsd文件,它有一个表适配器。 我想更改表适配器的命令超时。

谢谢你的帮助。

我今天对此问题进行了一些调查,并根据几个来源提出了以下解决方案。 我们的想法是为表适配器创建一个基类inheritance,这会增加表适配器中所有命令的超时,而不必重写太多的现有代码。 它必须使用reflection,因为生成的表适配器不会inheritance任何有用的东西。 如果你想删除我在构造函数中使用的东西并使用它,它会公开一个公共函数来改变超时。

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

通过一些小的修改,csl的想法很有效。

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

要使用它,只需设置this.FooTableAdapter.CommandTimeout = 60; 在this.FooTableAdapter.Fill()之前的某个地方;


如果需要更改许多表适配器的超时,可以创建一个通用扩展方法并让它使用reflection来更改超时。

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

用法:

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

这有点慢。 如果在错误类型的对象上使用它,则可能会出错。 (据我所知,没有“TableAdapter”类可以限制它。)

我在使用Mitchell Gilman的解决方案时遇到了一些问题,我最终能够解决这个问题。

首先,我需要确保使用正确的命名空间。 我花了一段时间才发现xsd数据集的Designer文件实际上包含两个名称空间,一个用于一般数据集,另一个用于表适配器。 所以首先要注意的是应该使用表适配器的命名空间,而不是一般的数据集。

其次,当第一次使用超时命令时,可能不会始终初始化commandcollection。 为了解决这个问题,我调用了InitCommandCollection命令(如果是这种情况)。

所以我使用的改编解决方案是

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

希望对人们有所帮助!

在某些情况下,您无法在类中访问类似Adapter的成员,因为它们被定义为类的私有

幸运的是,向导将生成部分类,这意味着您可以扩展它们。 如[Piebald的[此主题] [1]中所述,您可以编写自己的属性来设置select-commands的超时。

通常,你会这样做:

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

请注意,我自己并没有真正尝试过,但它似乎是一个可行的解决方案。

假设您的数据集名为MySET。
有一个名为MyTable的表

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

通过以秒为单位提供TableAdapter和Time来调用ChangeTimeout函数。

 this.ChangeTimeout(this.taTest, 500); 

function:

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

如果使用部分类,请使用正确的命名空间。 可能[您的数据集名称] +“TableAdapters”。示例:

命名空间MyProject.DataSet1TableAdapters

您可以打开Properties文件夹,打开Settings.settings并更改连接字符串的Timeout属性。

以下是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) 

这个现在有点老了,并怀疑这个解决方案与每个人都无关,但我最终使用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; } } } } 

我喜欢这个; 右键单击Fill()GetX()函数,然后单击菜单中的Goto Defination GetX()

您将看到DATATABLE的源代码。 并找到;

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

来自dataadapter类的命令行。 并将私人变为公众。

现在您可以访问_commandCollection,并且可以更改所有属性。

但是当你添加或更改任何Filed表单DESIGNER时要小心,公众将通过自动生成系统再次私有。

而且,当你完成调用Fill或Get Function时,你必须重置_commandColleciton调用这个函数( InitCommandCollection()

  public void InitCommandCollection() {} 

这个function也是autogen私有的,你也必须改为公开!

例:

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

扩展了帮助我很多的tableadapters已经非常有用的答案,我还需要读出实际的超时值。 从而:

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

似乎有一种更方便的方法来做到这一点。 这是我发现的快速回顾。

假设我将一个名为MyDB的(类库)项目添加到我的解决方案中。 在该项目中,我添加了一个名为“Data”的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); 

较少的麻烦,较少的烦恼,较少的reflection(好,没有),较少的填充。