【问题标题】:Set CommandTimeout used in Strongly Typed DataSet TableAdapter?设置在强类型数据集 TableAdapter 中使用的 CommandTimeout?
【发布时间】:2009-06-22 17:26:47
【问题描述】:

序言:

因此,在过去 5 年左右的时间里,我的公司已经编写了各种应用程序和工具。不幸的是,许多开发这些应用程序的人都使用了强类型数据集,我现在正在考虑在我们的商店中取缔它们......

使用强类型数据集的较大进程之一现在正在超时...我打算在接下来的几个月内使用 nHibernate 重写整个进程,但目前我需要更改超时以允许我们的用户使用该过程,尽管速度很慢...不幸的是,Microsoft 将 commandtimeout 方法设为私有,因此我无法直接访问它们。

到目前为止,我遇到的唯一解决方案是为每个 TableAdapter 创建一个部分类,并在其中包含超时方法......

这很笨拙,因为这意味着要为很多 TableAdapter 添加部分类...

有谁知道更有效的方法来处理这个问题?

【问题讨论】:

    标签: c# ado.net timeout strongly-typed-dataset


    【解决方案1】:

    我使用反射“解决”了这个问题。 (例如,虽然 VS2010 模型允许公开 Adapter 属性,但 SelectCommand 等将是 nullGetData 之前。)

    我目前正在使用的“丑陋但功能代码”:

    void SetAllCommandTimeouts(object adapter, int timeout)
    {
        var commands = adapter.GetType().InvokeMember(
                "CommandCollection",
                BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
                null, adapter, new object[0]);
        var sqlCommand = (SqlCommand[])commands;
        foreach (var cmd in sqlCommand)
        {
            cmd.CommandTimeout = timeout;
        }
    }
    
    // unfortunately this still requires work after a TableAdapter is obtained...
    var ta = new MyTableAdapter();
    SetAllCommandTimeouts(ta, 120);
    var t = ta.GetData();
    

    由于缺少通用基础/接口,实际上不可能更好地键入适配器(尽管可能是 Component)。

    编码愉快。

    【讨论】:

    • 对解决我的问题很有帮助。 :)
    【解决方案2】:

    你没有说你使用的是什么语言。以下是在VB.NET中,因为我碰巧首先找到了这样一个例子:

    Namespace AdventureWorksPurchasingDSTableAdapters
        Partial Public Class SalesOrderHeaderTableAdapter
        Public Property SelectCommandTimeout() As Integer
            Get
            Return Adapter.SelectCommand.CommandTimeout
            End Get
            Set(ByVal value As Integer)
            Adapter.SelectCommand.CommandTimeout = value
            End Set
        End Property
        End Class
    End Namespace
    

    【讨论】:

    • 是的,但这就是我试图避免做的事情......单独做起来很容易......如果你有数百个数据集的数百个表适配器,它真的不是很可行。
    • 我想不出你还能做什么。没有全局 CommandTimeout 属性。如果有,它仍然必须以某种方式设置单独的 SqlCommand.CommandTimeout 属性。
    • 为什么不能在数据集设计器中调整 CommandTimeout 属性?为什么当我将连接超时更改为 300 秒时它仍然是 30 秒?顺便说一句,这些有什么区别?在此先感谢...
    • 蒂姆,如果您有任何问题,请单独提出问题。这不是讨论组,cmet 也不是线程。
    • 这种方法对我不起作用。 SelectCommandnull 直到填充到像 GetData 这样的函数中。
    【解决方案3】:

    好的,据我所知,这些情况没有捷径/解决方法。感谢 John 的尝试。

    我最好的建议是不要在快速而肮脏的原型设计之外使用 MS 数据集...当您的应用程序增长并需要扩展时,您只剩下肮脏的东西了 :)

    【讨论】:

    • 这是一个相当狭窄的基础来谴责类型化的数据集。但是,它是关于 Connect (connect.microsoft.com/visualstudio) 功能建议的重要基础。发布建议后,使用建议的 URL 编辑此答案,以便其他人可以投票支持我们认为它的重要性。
    • 嗯,这个问题不是该声明的唯一基础...我对数据集的最大问题是缺乏智能默认值...如果您的配置文件没有正确的连接字符串然后它默认为它创建的任何连接字符串......我对这个问题的直觉是,在任何有歧义的情况下,唯一正确的响应是抛出异常并死亡......
    • 我会在今晚晚些时候将建议放在 Connect 上,我没有忽略您的建议 :)
    • 我发现强类型数据集很适合报告...这是我唯一使用它们的地方...
    【解决方案4】:

    我轻松解决了这个问题。我进入了我的数据集的设计器代码 (dataset1.designer.vb) 并找到了以下命令,Me._commandCollection(0)Me._commandCollection(1)Me._commandCollection(5),因为我总共有五个针对我的 SQL Server 2008 数据库执行的命令。在这些命令中的每一个(0 到 5)中,我都写了 Me._commandCollection(0).CommandTimeout = 60,在其中我将 0 更改为其他四个命令的下一个数字。五个命令中的每一个都有一个代码块,其中,下面出现两个代码块来为您提供示例。

    Me._commandCollection = New Global.System.Data.SqlClient.SqlCommand(5) {}
    
    Me._commandCollection(0) = New Global.System.Data.SqlClient.SqlCommand()
    
    Me._commandCollection(0).Connection = Me.Connection
    
    Me._commandCollection(0).CommandTimeout = 60
    
    Me._commandCollection(0).CommandText = "SELECT MK_QR_SUB_AND_DETAIL.*" & _ "Global.Microsoft.VisualBasic.ChrW(13) & Global.Microsoft.VisualBasic.ChrW(10)" & _ "FROM MK_QR_SUB_AND_DETAIL"
    
    Me._commandCollection(0).CommandType = Global.System.Data.CommandType.Text    
    
    Me._commandCollection(1) = New Global.System.Data.SqlClient.SqlCommand()
    
    Me._commandCollection(1).Connection = Me.Connection
    
    Me._commandCollection(1).CommandTimeout = 60
    
    Me._commandCollection(1).CommandText = "dbo.spQtrRptTesting_RunInserts_Step1of4"
    
    Me._commandCollection(1).CommandType = Global.System.Data.CommandType.StoredProcedure
    
    Me._commandCollection(1).Parameters.Add(New Global.System.Data.SqlClient.SqlParameter("@RETURN_VALUE", Global.System.Data.SqlDbType.Int, 4, Global.System.Data.ParameterDirection.ReturnValue, 10, 0, Nothing, Global.System.Data.DataRowVersion.Current, False, Nothing, "", "", ""))
    
    Me._commandCollection(1).Parameters.Add(New Global.System.Data.SqlClient.SqlParameter("@pStartADate", Global.System.Data.SqlDbType.[Date], 3, Global.System.Data.ParameterDirection.Input, 10, 0, Nothing, Global.System.Data.DataRowVersion.Current, False, Nothing, "", "", ""))
    
    Me._commandCollection(1).Parameters.Add(New Global.System.Data.SqlClient.SqlParameter("@pEndADate", Global.System.Data.SqlDbType.[Date], 3, Global.System.Data.ParameterDirection.Input, 10, 0, Nothing, Global.System.Data.DataRowVersion.Current, False, Nothing, "", "", ""))
    
    Me._commandCollection(1).Parameters.Add(New Global.System.Data.SqlClient.SqlParameter("@pStartBDate", Global.System.Data.SqlDbType.[Date], 3, Global.System.Data.ParameterDirection.Input, 10, 0, Nothing, Global.System.Data.DataRowVersion.Current, False, Nothing, "", "", ""))
    
    Me._commandCollection(1).Parameters.Add(New Global.System.Data.SqlClient.SqlParameter("@pEndBDate", Global.System.Data.SqlDbType.[Date], 3, Global.System.Data.ParameterDirection.Input, 10, 0, Nothing, Global.System.Data.DataRowVersion.Current, False, Nothing, "", "", ""))
    

    【讨论】:

    • 警告:永远不要手动编辑 designer 文件。这是自动生成的代码,您在其中编写的所有内容都可以在 Visual Studio 重新生成代码时被覆盖。
    【解决方案5】:

    我决定在派生 TableAdapter 类的 DataSet.cs 文件中创建一个新类,并在构造函数中检查 App.config 中的命令超时。我还添加了为特定表适配器指定命令超时的功能,如果不存在,则检查全局值。

    public class ImprovedMyTableAdapter : MyTableAdapter
    {
        public ImprovedMyTableAdapter()
            : base()
        {
            int parsedInt = int.MinValue;
            string appSettingValue = System.Configuration.ConfigurationManager.AppSettings["MyTableAdapter_CommandTimeout"];
            if (string.IsNullOrEmpty(appSettingValue))
                appSettingValue = System.Configuration.ConfigurationManager.AppSettings["CommandTimeout"];
            if (!string.IsNullOrEmpty(appSettingValue) && int.TryParse(appSettingValue, out parsedInt))
            {
                foreach (var command in this.CommandCollection)
                    command.CommandTimeout = parsedInt;
            }
        }
    }
    

    【讨论】:

      【解决方案6】:

      我不会直接弄乱 DataSet 设计器的代码 b/c 如果您更新设计器中的任何内容,它将被更改。而是为表适配器创建一个部分类,并为其提供一个接受命令超时参数并调用无参数构造函数的构造函数。

      然后遍历 CommandCollection 并将超时设置为传入的超时参数。

      【讨论】:

        【解决方案7】:

        它已经过时了,但有时您会使用旧的解决方案...

        首先,创建这个基类:

        using System;
        using System.Data;
        using System.Data.SqlClient;
        using System.Linq;
        using System.Reflection;
        
        namespace PhotoReport.Data
        {
            public class DataAdapterCustomBase : global::System.ComponentModel.Component
            {
                public void SetTimeout(int value)
                {
                    SqlCommand[] innerCommands = this.GetType().InvokeMember(
                        "CommandCollection",
                        BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
                        null, this, null) as SqlCommand[];
        
                    if (!ReferenceEquals(innerCommands, null))
                    {
                        foreach (SqlCommand cmd in innerCommands)
                        {
                            cmd.CommandTimeout = value;
                        }
                    }
                }
            }
        }
        

        之后,在 DataSet 设计器中,选择您的表适配器并将 BaseClass 属性更改为您的自定义基类(在我的例子中是 PhotoReport.Data.DataAdapterCustomBase)。

        最后,你可以使用:

        using (svcServiceAppointmentsTableAdapter tableAdapter = new svcServiceAppointmentsTableAdapter()) 
        {
            tableAdapter.SetTimeout(60);
        
            // do your stuff
        }
        

        【讨论】:

          猜你喜欢
          • 2015-05-09
          • 1970-01-01
          • 2010-12-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多