【发布时间】:2010-11-14 14:21:20
【问题描述】:
我正在使用带有 C# 的 Visual Studio 2008。
我有一个 .xsd 文件,它有一个表适配器。我想更改表适配器的命令超时。
感谢您的帮助。
【问题讨论】:
标签: c# dataset timeout command
我正在使用带有 C# 的 Visual Studio 2008。
我有一个 .xsd 文件,它有一个表适配器。我想更改表适配器的命令超时。
感谢您的帮助。
【问题讨论】:
标签: c# dataset timeout command
假设您的数据集名为 MySET。
有一张表叫 MyTable
MySETTableAdapters.MyTableTableAdapter fAdapter =
new MySETTableAdapters.MyTableTableAdapter();
fAdapter.Adapter.SelectCommand.CommandTimeout = <fill inyour value here>;
【讨论】:
TableAdapter 不公开Adapter 属性,它是private。所以除了refelction,唯一的办法就是扩展TableAdapter的partial类使其公开。
在某些情况下,您无法在类中访问像 Adapter 这样的成员,因为它们被定义为类的私有。
幸运的是,向导会生成部分类,这意味着您可以扩展它们。如 [this thread by Piebald][1] 中所述,您可以编写自己的属性来设置选择命令的超时时间。
通常,您会这样做:
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;
}
}
}
请注意,我自己并没有真正尝试过,但这似乎是一个可行的解决方案。
【讨论】:
经过一些小的修改,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; this.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”类可以限制它。)
【讨论】:
如果您使用分部类,请确保您拥有正确的命名空间。可能是 [您的数据集的名称] + "TableAdapters"。示例:
命名空间 MyProject.DataSet1TableAdapters
【讨论】:
我今天对此问题进行了一些调查,并根据一些来源提出了以下解决方案。 这个想法是为表适配器创建一个基类,从而增加表适配器中所有命令的超时时间,而无需重写太多现有代码。它必须使用反射,因为生成的表适配器不会继承任何有用的东西。如果您想删除我在构造函数中使用的内容并使用它,它会公开一个公共函数来更改超时。
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 数据集的 Designer 文件实际上包含两个命名空间,一个用于一般数据集,一个用于表适配器。所以首先要注意的是,应该使用表适配器的命名空间,而不是一般的数据集。
其次,第一次使用 timeout 命令时,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;
}
}
}
希望对人们有所帮助!
【讨论】:
您可以打开 Properties 文件夹,打开 Settings.settings 并更改连接字符串的 Timeout 属性。
【讨论】:
我喜欢这个;右键单击Fill() 或GetX() 函数,然后从菜单中单击Goto Defination。
您将看到 DATATABLE 的源代码。并找到;
private global::System.Data.SqlClient.SqlCommand[] _commandCollection;
dataadapter 类的命令行。 并将私有更改为公共。
现在您可以访问 _commandCollection 并且可以更改所有属性。
但是当您添加或更改任何归档表单 DESIGNER 时要小心,自动生成系统将再次将公众设为私有。
而且,当您完成调用 Fill 或 Get 函数时,您必须重置 _commandColleciton 调用此函数 (InitCommandCollection())
public void InitCommandCollection() {}
这个函数也是autogen私有的,你也必须改为public!
例子:
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();
【讨论】:
通过提供 TableAdapter 和时间(以秒为单位)来调用 ChangeTimeout 函数。
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;
}
【讨论】:
这是来自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's 解决方案来覆盖 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;
}
}
}
}
【讨论】:
扩展了对我有很大帮助的 tableadapter 已经非常有用的答案,我还需要读出实际的超时值。因此:
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;
}
}
}
}
}
【讨论】:
似乎有一种更方便的方法可以做到这一点。以下是我发现的快速回顾。
假设我在我的解决方案中添加了一个名为 MyDB 的(类库)项目。在该项目中,我添加了一个名为“Data”的数据集。在那个数据集中,我拖动一个名为“X”的表。
我在设计图面上看到的是一个对象,它表明我有一个名为“XTableAdapter”的对象。
我现在打开生成的代码 Data.Designer.cs,然后查找 XTableAdapter。 当我找到它时,我注意到它包含在命名空间 MyDB.DataTableAdapters 中——它只是项目名称、“MyDB”、DataSet 名称、“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);
更少的混乱,更少的大惊小怪,更少的反思(好吧,没有),更少的填充。
【讨论】:
如果你去[name of 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等
【讨论】:
在挠了一天的头之后,我终于得到了这个解决方案。设计完 .xsd 文件后,您需要做的就是转到您的 dataset.designer.cs 页面,这是一个自动生成的页面,并将代码更改为下面提供的代码。真的行。试一试。
protected global::System.Data.SqlClient.SqlCommand[] CommandCollection
{
get
{
if ((this._commandCollection == null))
{
this.InitCommandCollection();
_commandCollection[0].CommandTimeout = 0;
}
_commandCollection[0].CommandTimeout = 0;
return this._commandCollection;
}
}
【讨论】: