全局控制TableAdapter命令超时

时间:2009-06-10 14:20:54

标签: c# tableadapter

我有一个带有QueriesTableAdapter的DataSet。为了控制SqlCommand.CommandTimeout,我添加了一个名为QueriesTableAdapter的分部类,其中包含一个名为ChangeTimeout的公共方法。

partial class QueriesTableAdapter
{
    public void ChangeTimeout(int timeout)
    {
        foreach (System.Data.SqlClient.SqlCommand cmd in CommandCollection)
        {
            cmd.CommandTimeout = timeout;
        }
    }
}

对于每个拥有QueriesTableAdapter的DataSet,我可以在执行之前设置CommandTimeout。

using (NameSpace.DataSet.DataSetTableAdapters.QueriesTableAdapter ta =
new NameSpace.DataSet.DataSetTableAdapters.QueriesTableAdapter())
{
    ta.ChangeTimeout(3600);
    ta.DoSomething();
}

这种方法很有效,因为“QueriesTableAdapter”是在DataSet设计器中为您命名的。我遇到的问题是具有唯一名称的TableAdapter。例如,如果我有一个名为Person的DataTable和一个名为PersonTableAdapter的TableAdaper,我必须像编写QueriesTableAdaper类一样编写PersonTableAdapter分部类。我有数百个具有唯一TableAdapter名称的DataTable。我不想为每个人创建一个部分类。如何以全局方式访问部分类的基础SqlCommand对象?

4 个答案:

答案 0 :(得分:11)

由于某种原因,我的适配器的.select命令为null所以我最终不得不通过CommandCollection对象,所以我想我会根据上面的答案发布我的小改动。

包括:

using System.ComponentModel;
using System.Reflection;

代码:

private void ChangeTimeout(Component component, int timeout)
        {
            if (!component.GetType().Name.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;
            }

            command[0].CommandTimeout = timeout;            
        }

答案 1 :(得分:3)

所有生成的TableAdapter都继承自Component。因此,您可以编写一个这样的方法,使用反射来提取适配器属性:

    private void ChangeTimeout(Component component, int timeout)
    {
        if (!component.GetType().Name.Contains("TableAdapter"))
        {
            return;
        }

        PropertyInfo adapterProp = component.GetType().GetProperty("Adapter", BindingFlags.NonPublic | BindingFlags.GetProperty | BindingFlags.Instance);
        if (adapterProp == null)
        {
            return;
        }

        SqlDataAdapter adapter = adapterProp.GetValue(component, null) as SqlDataAdapter;
        if (adapter == null)
        {
            return;
        }

        adapter.SelectCommand.CommandTimeout = timeout;
    }

然后您可以这样称呼它:

MyTableAdapter ta = new MyTableAdapter();
this.ChangeTimeout(ta,1000);

我假设因为你使用的是类型化的DataSet,所以你仍然使用.NET 2.0,这就是为什么我不打算将它作为扩展方法。

答案 2 :(得分:1)

BFree和Mark的类似解决方案适用于反射。下面是一个细微的改进,我认为产生更整洁的代码。

您还可以更改TableAdapter在DataSet设计器中使用的基类。您可以将TableAdapter的基类更改为 MyTableAdapterBaseClass 或类似,以提供所需的功能。您可以通过执行“在文件中查找”并替换DataSet的.xsd文件,在所有TableAdapter上快速进行此更改。

而不是带有签名的调用者的BFree方法:

private void ChangeTimeout(Component component, int timeout)

然后,您可以在callee TableAdapter的基类上创建一个带签名的方法:

public void ChangeTimeout(int timeout)

答案 3 :(得分:0)

我尝试了两种选择并提出了一些问题 On 1st回答哪个命名空间必须导入/用于CommandCollection对象 on 2ns Answer adapter.SelectCommand返回空值