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

Wor*_*red 1 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);
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来做我想做的事情?"更好"的意思是要么是资源密集程度较低的方法来完成相同的任务,要么是更确定的方式来完成相同的任务(即我所知道的所有代码片段在某些情况下都会失败).

解决方案:首先,我的TOP 0黑客很糟糕,就像这样:

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

换句话说,在子选择中,如果两个东西别名为同名,则会引发错误.所以它是不合适的.但是,为了完整起见,我继续进行测试,并提出了两个建议的解决方案: SET FMTONLY ONGetSchemaTable.

以下是结果(每1000个查询的毫秒数):

架构时间:3130

TOP 0时间:2808

FMTONLY ON时间:2937

我的建议是,GetSchemaTable因为它更有可能通过删除SET FMTONLY ON有效的SQL而面向未来,并且它解决了别名问题,即使它稍慢. 但是,如果您"知道"重复的列名称永远不会成为问题,那么TOP 0比它更快,GetSchemaTable并且未来更具有前瞻性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();
Run Code Online (Sandbox Code Playgroud)

Mic*_*odd 5

您可以使用GetSchemaTable来执行您想要的操作.

还有就是如何使用它的一个例子在这里.