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

时间:2009-07-28 06:09:32

标签: c# dataset timeout command

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

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

感谢您的帮助。

15 个答案:

答案 0 :(得分:11)

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

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

答案 1 :(得分:10)

通过一些小的修改,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”类可以限制它。)

答案 2 :(得分:4)

我使用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;
    }
  }
}

希望对人们有所帮助!

答案 3 :(得分:2)

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

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

通常,你会这样做:

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

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

答案 4 :(得分:1)

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

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

答案 5 :(得分:1)

通过以秒为单位提供TableAdapter和Time来调用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;
}

答案 6 :(得分:0)

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

命名空间MyProject.DataSet1TableAdapters

答案 7 :(得分:0)

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

答案 8 :(得分:0)

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

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

private global::System.Data.SqlClient.SqlCommand[] _commandCollection;
来自dataadapter类的

命令行。 并将私人变为公众。

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

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

此外,当您完成调用Fill或Get Function时,您必须重置_commandColleciton调用此函数(InitCommandCollection()

 public void InitCommandCollection() {}

此功能也是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();

答案 9 :(得分:0)

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

答案 10 :(得分:0)

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

答案 11 :(得分:0)

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

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

        }
    }

}

答案 12 :(得分:0)

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

我想说我在我的解决方案中添加了一个名为MyDB的(类库)项目。在该项目中,我添加了一个名为&#34; Data&#34;的DataSet。在该数据集中,我拖了一个名为&#34; X&#34;。

的表

我在设计界面得到的是一个对象,它表明我有一个名为&#34; XTableAdapter&#34;的对象。

我现在打开生成的代码Data.Designer.cs,然后查找XTableAdapter。 当我找到它时,我注意到它包含在命名空间MyDB.DataTableAdapters中 - 它只是项目名称的连接,&#34; MyDB&#34;,DataSet的名称,&#34 ;数据&#34;和&#34; TableAdapters&#34;。

有了这个,我现在回到类库,仍称为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);

减少麻烦,减少烦恼,减少反思(嗯,没有),减少填充。

答案 13 :(得分:0)

如果转到[DataSet的名称] .Designer.cs,它是在解决方案中的数据集文件下添加的文件,然后搜索:

    $xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>
<request>
  <request-type>9</request-type>
  <terminal-id>".$termid."</terminal-id>
  <login>".$login."</login>
  <password-md5>".$pwd."</password-md5>
  <message txn-id=\"".$txn."\" sign=\"".$sign."\">
  <to>
    <source-address>".$source_address."</source-address>
    <destination-address>".$mobile_number."</destination-address>
    <data-encoding>1</data-encoding>
    <text>".$message."</text>
  </to>
  </message>
</request>";

$ch = curl_init();
$url = "http://gate.payvand.tj/xml/";
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_HTTPHEADER, Array("Content-Type: text/xml"));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
curl_setopt($ch, CURLOPT_FORBID_REUSE, true); 
curl_setopt($ch, CURLOPT_TIMEOUT, 60);

这是一个函数,您应该能够为在表适配器中定义的函数设置属性。

该函数的第一行是

 private void InitCommandCollection();

,然后在每个功能的下一行中,设置

this._commandCollection = new global::System.Data.IDbCommand[<number of function defined in a table adapater>];

其中0表示没有限制,并且该功能不会因超时而停止,并且可以将其设置为10、20、30或1000,依此类推

答案 14 :(得分:0)

整天挠头后,我终于得到了解决方案。设计完.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;
        }
    }