c# - 在 C# 中, "SELECT TOP 0 * FROM (/* ... */) s"与 ADO.NET 结合使用是否是确定 SELECT 语句中的列信息的好方法?

标签 c# sql ado.net

我有一个直到运行时才知道的 SQL SELECT 语句,它可能包含 JOIN 和内部选择。我需要从 C# 中确定语句返回结果的每一列的名称和数据类型。我倾向于做类似的事情:

string orginalSelectStatement = "SELECT * FROM MyTable";

string selectStatement = string.Format("SELECT TOP 0 * FROM ({0}) s", orginalSelectStatement);
SqlConnection connection = new SqlConnection(@"MyConnectionString");
SqlDataAdapter adapter = new SqlDataAdapter(selectStatement, connection);

DataTable table = new DataTable();
adapter.Fill(table);

foreach (DataColumn column in table.Columns)
{
    Console.WriteLine("Name: {0}; Type: {1}", column.ColumnName, column.DataType);
}

是否有更好的方法来完成我想做的事情?所谓“更好”,我指的是完成同一任务的资源密集度较低的方法,或者是完成同一任务的更可靠的方法(即据我所知,我刚刚给出的代码片段在某些情况下会失败)。

解决方案: 首先,我的 TOP 0 hack 很糟糕,即对于这样的事情:

SELECT TOP 0 * FROM (SELECT 0 AS A, 1 AS A) S

换句话说,在子选择中,如果两个事物的别名相同,则会引发错误。所以它不在画面中。然而,为了完整起见,我继续测试它,以及两个建议的解决方案:SET FMTONLY ONGetSchemaTable

结果如下(1,000 次查询,每次以毫秒为单位):

Schema Time: 3130

TOP 0 Time: 2808

FMTONLY ON Time: 2937

我的建议是 GetSchemaTable,因为它更有可能通过删除作为有效 SQL 的 SET FMTONLY ON 来面向 future ,并且它解决了别名问题,尽管速度稍慢。 但是,如果您“知道”重复的列名永远不会成为问题,那么 TOP 0GetSchemaTable 更快,而且更具 future 感-证明比 SET FMTONLY ON

这是我的实验代码:

int schemaTime = 0;
int topTime = 0;
int fmtOnTime = 0;

SqlConnection connection = new SqlConnection(@"MyConnectionString");
connection.Open();

SqlCommand schemaCommand = new SqlCommand("SELECT * FROM MyTable", connection);
SqlCommand topCommand = new SqlCommand("SELECT TOP 0 * FROM (SELECT * FROM MyTable) S", connection);
SqlCommand fmtOnCommand = new SqlCommand("SET FMTONLY ON; SELECT * FROM MyTable", connection);

for (int i = 0; i < 1000; i++)
{
    {
        DateTime start = DateTime.Now;
        using (SqlDataReader reader = schemaCommand.ExecuteReader(CommandBehavior.SchemaOnly))
        {
            DataTable table = reader.GetSchemaTable();
        }
        DateTime stop = DateTime.Now;
        TimeSpan span = stop - start;
        schemaTime += span.Milliseconds;
    }

    {
        DateTime start = DateTime.Now;

        DataTable table = new DataTable();
        SqlDataAdapter adapter = new SqlDataAdapter(topCommand);
        adapter.Fill(table);

        DateTime stop = DateTime.Now;
        TimeSpan span = stop - start;
        topTime += span.Milliseconds;
    }

    {
        DateTime start = DateTime.Now;

        DataTable table = new DataTable();
        SqlDataAdapter adapter = new SqlDataAdapter(fmtOnCommand);
        adapter.Fill(table);

        DateTime stop = DateTime.Now;
        TimeSpan span = stop - start;
        fmtOnTime += span.Milliseconds;
    }
}

Console.WriteLine("Schema Time: " + schemaTime);
Console.WriteLine("TOP 0 Time: " + topTime);
Console.WriteLine("FMTONLY ON Time: " + fmtOnTime);

connection.Close();

最佳答案

你可以使用 GetSchemaTable做你想做的。

有一个如何使用它的例子here .

关于c# - 在 C# 中, "SELECT TOP 0 * FROM (/* ... */) s"与 ADO.NET 结合使用是否是确定 SELECT 语句中的列信息的好方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10216670/

相关文章:

.net - ADO.NET:DataSet 或 DataTable 以及如何检索数据

c# - 如何正确使用 SqlDataReader?

c# - 良好的 Lucene .NET 替代 ASP.NET 网站

c# - 检查组合框 : How to prevent a combobox from closing after a selection is clicked?

sql - 识别 MS Access 中文本字段中的数字

sql - 有条件地替换 SELECT 中的值

sql - 使用 ADO .NET 调用 SQL 函数

c# - 在C#中创建绝对Uri

c# - Assembly.GetTypes() - ReflectionTypeLoadException

MySql - 循环遍历每一行的一个月中的日期