设置强类型DataSet TableAdapter中使用的CommandTimeout?

时间:2009-06-22 17:26:47

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

序言:

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

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

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

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

任何人都知道一种更有效的方法来处理这个问题吗?

7 个答案:

答案 0 :(得分:3)

我用反射“解决了”这个问题。 (虽然VS2010模型允许公开Adapter属性,但SelectCommand等在null之前将为GetData。)

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

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)。

快乐的编码。

答案 1 :(得分: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

答案 2 :(得分:2)

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

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

答案 3 :(得分:0)

我轻松解决了这个问题。我进入了我的数据集的设计器代码(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, "", "", ""))

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

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

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

答案 6 :(得分:0)

它很旧,但有时您会采用旧的解决方案...

首先,创建此基类:

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

然后,在数据集设计器中,选择表适配器,然后将BaseClass属性更改为“自定义基类”(在我的情况下为PhotoReport.Data.DataAdapterCustomBase)。

最后,您可以使用:

using (svcServiceAppointmentsTableAdapter tableAdapter = new svcServiceAppointmentsTableAdapter()) 
{
    tableAdapter.SetTimeout(60);

    // do your stuff
}