C# 全局控制 TableAdapter 命令超时

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/975898/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 04:40:41  来源:igfitidea点击:

Control TableAdapter Command Timeout Globally

c#tableadapter

提问by Billy Coover

I have a DataSet with a QueriesTableAdapter. In order to control the SqlCommand.CommandTimeout I've added a partial class called QueriesTableAdapter with a public method called ChangeTimeout.

我有一个带有 QueriesTableAdapter 的数据集。为了控制 SqlCommand.CommandTimeout,我添加了一个名为 QueriesTableAdapter 的部分类和一个名为 ChangeTimeout 的公共方法。

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

For every DataSet I have that has a QueriesTableAdapter, I can set the CommandTimeout prior to executing.

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

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

This works well is most cases because the "QueriesTableAdapter" is named for you in the DataSet designer. The problem I'm running into is the TableAdapters that are uniquely named. For example, if I have a DataTable called Person and a TableAdaper called PersonTableAdapter, I have to write a PersonTableAdapter partial class in the same way I wrote the QueriesTableAdaper class. I have hundreds of DataTables with unique TableAdapter names. I don't want to create a partial class for each of those. How can I get to the underlying SqlCommand objects of a partial class in a global way?

这在大多数情况下都很有效,因为在 DataSet 设计器中为您命名了“QueriesTableAdapter”。我遇到的问题是唯一命名的 TableAdapter。例如,如果我有一个名为 Person 的 DataTable 和一个名为 PersonTableAdapter 的 TableAdaper,我必须以与编写 QueriesTableAdaper 类相同的方式编写一个 PersonTableAdapter 部分类。我有数百个具有唯一 TableAdapter 名称的数据表。我不想为每个类创建一个部分类。如何以全局方式访问部分类的底层 SqlCommand 对象?

采纳答案by mark

for some reason, my adapter's .selectcommand was null so i ended up having to go through the CommandCollection object instead, so i thought i'd post my small change based on the previous answer above.

出于某种原因,我的适配器的 .selectcommand 为空,所以我最终不得不通过 CommandCollection 对象,所以我想我会根据上面的先前答案发布我的小改动。

includes:

包括:

using System.ComponentModel;
using System.Reflection;

code:

代码:

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

回答by BFree

All generated TableAdapters inherit from Component. Therefore, you could write a method like this that uses reflection to extract the adapter property:

所有生成的 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;
    }

You then can call it like this:

然后你可以这样称呼它:

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

I'm assuming that since you're using typed DataSet's that you're still in .NET 2.0 which is why I didn't bother making this an extension method.

我假设由于您使用的是类型化数据集,因此您仍在 .NET 2.0 中,这就是为什么我没有费心将其作为扩展方法。

回答by BFree

I have tried both the options and giving some issues On 1st Answer which namespace have to be imported/used for CommandCollection object on 2ns Answer adapter.SelectCommand is returning null value

我已经尝试了这两个选项并给出了一些问题 On 1st Answer 必须为 2ns Answer 适配器上的 CommandCollection 对象导入/使用哪个命名空间。SelectCommand 返回空值

回答by Alex

BFree and mark's similar solutions work well with reflection. Below is a slight refinement that I think yields neater code.

BFree 和 mark 的类似解决方案与反射配合得很好。下面是我认为会产生更整洁代码的轻微改进。

You can also change the base class that the TableAdapter uses in the DataSet designer. You can change your TableAdapter's base class to MyTableAdapterBaseClassor similar to provide the functionality you need. You can make this change quickly on all your TableAdapters by doing a 'Find in Files' and replace on your DataSets' .xsd files.

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

Instead of BFree's method on the caller with signature:

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

private void ChangeTimeout(Component component, int timeout)

you can then create a method on the callee TableAdapter's base class with signature:

然后,您可以使用签名在被调用方 TableAdapter 的基类上创建一个方法:

public void ChangeTimeout(int timeout)