SqlDataReader使用相同名称的GetOrdinal函数

5

我需要使用SqlDataReader中的GetOrdinal,但我的查询包含多个相同字段名,并且有多个联接。因此,我尝试使用以下代码:

SELECT a.Id, b.Id FROM table1 AS a ...

但是GetOrdinal似乎不理解模式别名... GetOrdinal('a.Id')会抛出异常...有什么方法可以解决这个问题吗?

你为什么需要名称呢?你可以使用 reader.GetInt32(0)reader.GetInt32(1) - Tim Schmelter
2个回答

9

在您的查询中给一个别名

SELECT a.Id As EmployeeID, b.Id as ManagerId FROM table1 AS a ..

现在,您可以在代码中使用别名来读取值。
var employeeIdIndex = reader.GetOrdinal("EmployeeID")

那就是我尝试避免的 :) - Sebastian
2
你为什么想要避免那个? - Shyju
但是使用架构别名后,它在某种程度上是独一无二的,因此需要做更多的工作。 - Sebastian
@Sebastian,我认为你正在错误的方向上解决问题。你想要实现什么目标? - Shyju
我有一个类似于我描述的语句,在应用程序中,我知道模式别名和字段名称,因此我需要列的索引来获取数据。但似乎以这种方式不可能。 - Sebastian

5

我自己也曾有过这个问题,而我发现两种常见的答案是:

  • 在你的SQL中给字段起一个别名
  • 使用列的整数索引

我不喜欢这两个选项,所以我创造了第三种方法:GetNthOrdinal。

using System;
using System.Data;
using System.Data.SqlClient;
using System.Linq;

public static class SqlDataReaderExtensions
{
    public static int GetNthOrdinal(this SqlDataReader reader, string columnName, int nthOccurrence = 1)
    {
        // Get the schema which represents the columns in the reader
        DataTable schema = reader.GetSchemaTable();

        // Find all columns in the schema which match the name we're looking for.
        // schema is a table and each row is a column from our reader.
        var occurrences = schema.Rows.Cast<DataRow>().Where(r => string.Equals((string)r["ColumnName"], columnName, StringComparison.Ordinal));

        // Get the nthOccurrence.  Will throw if occurrences is empty.
        // reader.GetOrdinal will also throw if a column is not present, but you may want to
        // have this throw a more meaningful exception
        var occurrence = occurrences.Skip(nthOccurrence - 1).First();

        // return the ordinal
        return (int)occurrence["ColumnOrdinal"];
    }
}

使用方法:

reader.GetNthOrdinal("Id", 2);

重要提示:第N次出现并非从0开始计数,而是从1开始计数。

1
几年后回来看这个问题,我想说别名不是我的选择主要原因是我没有修改SQL的能力。如果有修改SQL查询的能力,那么别名是最好的选择。 - dshapiro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接