【问题标题】:How can I change the table adapter's command timeout如何更改表适配器的命令超时
【发布时间】:2010-11-14 14:21:20
【问题描述】:

我正在使用带有 C# 的 Visual Studio 2008。

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

感谢您的帮助。

【问题讨论】:

    标签: c# dataset timeout command


    【解决方案1】:

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

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

    【讨论】:

    • -1 这不起作用,因为强类型的TableAdapter 不公开Adapter 属性,它是private。所以除了refelction,唯一的办法就是扩展TableAdapter的partial类使其公开。
    【解决方案2】:

    在某些情况下,您无法在类中访问像 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;
        }
      }
    }
    

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

    【讨论】:

    • 谢谢!我无法让它为我工作,因为 _commandCollection 为空。我做了一些更新并将其作为另一个答案发布。
    【解决方案3】:

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

    【讨论】:

    • 效果很好!谢谢你在大约 10 年前帮助我写你的帖子,哈哈
    【解决方案4】:

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

    命名空间 MyProject.DataSet1TableAdapters

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

        【解决方案6】:

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

        希望对人们有所帮助!

        【讨论】:

          【解决方案7】:

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

          【讨论】:

            【解决方案8】:

            我喜欢这个;右键单击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();
            

            【讨论】:

              【解决方案9】:

              通过提供 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;
              }
              

              【讨论】:

              • 什么是交互?
              【解决方案10】:

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

              【讨论】:

                【解决方案11】:

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

                【讨论】:

                  【解决方案12】:

                  扩展了对我有很大帮助的 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;
                                      }
                              }
                  
                          }
                      }
                  
                  }
                  

                  【讨论】:

                    【解决方案13】:

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

                    假设我在我的解决方案中添加了一个名为 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);
                    

                    更少的混乱,更少的大惊小怪,更少的反思(好吧,没有),更少的填充。

                    【讨论】:

                      【解决方案14】:

                      如果你去[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等

                      【讨论】:

                        【解决方案15】:

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

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2011-01-20
                          • 2017-11-08
                          • 1970-01-01
                          • 1970-01-01
                          • 2020-10-06
                          • 1970-01-01
                          • 1970-01-01
                          • 2015-03-26
                          相关资源
                          最近更新 更多