我正在使用带有C#的Visual Studio 2008。
我有一个.xsd文件, 其中有一个表适配器。我想要更改表适配器的命令超时时间。
感谢您的帮助。
通过一些小的修改,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.Fill()之前的某个地方设置this.FooTableAdapter.CommandTimeout = 60;。
如果您需要更改许多表适配器的超时时间,可以创建一个通用扩展方法,并使用反射来更改超时时间。
/// <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”类上的方法。)
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);
}
}
}
我使用Mitchell Gilman的解决方案时遇到了几个问题,但最终设法解决了。
首先,我需要确保使用正确的命名空间。我花了一些时间才弄清楚xsd数据集的设计器文件实际上包含两个命名空间,一个用于数据集总体,另一个用于表适配器。因此,第一件事是要注意使用表适配器的命名空间,而不是数据集的命名空间。
其次,当第一次使用超时命令时,命令集合可能并不总是被初始化。为了解决这个问题,如果命令集合未被初始化,我调用了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;
}
}
}
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;
}
}
}
假设你的数据集名字叫MySET。
其中有一张表格叫MyTable。
MySETTableAdapters.MyTableTableAdapter fAdapter =
new MySETTableAdapters.MyTableTableAdapter();
fAdapter.Adapter.SelectCommand.CommandTimeout = <fill inyour value here>;
TableAdapter
不会公开 Adapter
属性,它是 private
的。所以除了反射之外,唯一的方法就是扩展 TableAdapter
的部分类使其变为公共的。 - Tim Schmelter这里是来自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
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)
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;
}
看起来有更方便的方法来完成这个任务。以下是我找到的快速总结。
假设我在解决方案中添加了一个名为MyDB的(类库)项目。我在该项目中添加了一个名为“Data”的DataSet,并在该数据集中拖动了一个名为“X”的表。
在设计界面上,我得到了一个对象,显示我有一个名为“XTableAdapter”的对象。
现在我打开生成的代码Data.Designer.cs,并查找XTableAdapter。当我找到它时,我注意到它包含在MyDB.DataTableAdapters命名空间中——这只是项目名称“MyDB”、数据集名称“Data”和“TableAdapters”的连接。
有了这个信息,我现在回到仍然称为Class1.cs的类库(我现在将其忽略)。
我将它的命名空间从MyDB更改为MyDB.DataTableAdapters。
我更改了类声明为public partial class 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);