有没有办法在 ado .net 中使用完全限定的 sql 列名?

Is there a way to use fully qualified sql column names in ado .net?

我正在努力将数据库(大约 30 table 秒)连接到我的 .net Web API。 现在我使用以下代码:

public static int GetIntNullCheck(IDataRecord reader, string columnName, int valueIfNull = -1)
{
    if (reader == null)
        throw new ArgumentNullException(nameof(reader));
    int ordinal = reader.GetOrdinal(columnName);
    return reader.IsDBNull(ordinal) ? valueIfNull : reader.GetInt32(ordinal);
}

因为我的一些查询连接了许多 table,所以我想使用完全限定的列名来访问结果。 在 ado.net 中有没有一种干净的方法来做到这一点?互联网上有多个关于此主题的已回答问题,但在我的情况下,每个解决方案都是黑客或不切实际。

想过但不想用的东西:

1.对冲突的列名称使用 SQL 列别名

这在理论上是可行的,但我的查询已经非常大了,对于每个查询 20 多个列这样做是不切实际的

2。更改数据库以在整个数据库中具有唯一的列名称

这可能是最现实的解决方案,但列名变得非常混乱。如果我没有其他选择,我必须这样做,但我真的很想避免它。

3。使用SQLDataReader.GetSchemaTable()自己写这个功能

首先我不喜欢这个,因为它感觉像是一个 hack,并且可能对性能不利。此外,这不适用于 table 别名,但我必须在我的一些自连接查询中使用这些别名。尽管如此,我还是尝试实现它,但我只在 table 的 BaseTableName 字段上获得空值,尽管我使用 command.ExecuteReader(CommandBehavior.KeyInfo))

3。使用不同的数据库连接库

Ado.Net 被广泛使用,我主要使用许多人使用的库,因为它们更容易维护——如果我对它们有问题,几乎可以肯定互联网上有 100 个其他人有同样的问题并且有博客文章讨论解决方案。如果 ado.net.

中没有干净的方法,我会切换库

必须有一个好的方法来做到这一点。就像我提到的,有很多人有这个问题,ado.net 足够大,所以应该支持它。我只想能够使用 reader.GetOrdinal(tableName + "." + columnName);。我总是将它与 java 中的 JDBC 一起使用,因此它必须可以从 SQL 侧

因此我的问题是:

我是否错过了一些可能的解决方案,或者您认为我描述的其中一个解决方案比我想象的要好?

tl;博士;美国别名。这就是他们在那里的目的。

Is there a way to use fully qualified sql column names in ado .net?

没有。结果集根据标识符的最后部分获取它的列名,即使您使用的是 multi-part 标识符 - 我很确定这不是 ADO.Net 的东西,因为它也发生在 SSMS 中(或我知道的任何其他数据库客户端)。

如果您 运行 在任何 SQL 服务器数据库上执行以下查询,您将自己看到它:

SELECT c.Name
     , c.Name As [Column Name]
     , T.Name
     , T.Name As [Table Name]
FROM sys.Tables As T
JOIN sys.Columns As C 
    ON C.object_id = T.object_id

你得到的列名是这些:

Name    Column Name     Name    Table Name

Things I thought about but do not want to use:

  1. Use SQL column aliases for conflicting column names

这实际上是该问题的最佳解决方案,因为它最容易实施和维护。
您不必为每个查询的所有列设置别名,只需为导致冲突的列设置别名。通常,不会那么多。

  1. Alter the database to have unique column names across the whole database

这似乎是一个可以接受的想法table,但它很快就会变得非常麻烦。
我曾经设计了一个数据库,所有列都以包含 table 的名称作为前缀。
当您有 table 时很容易,例如 UsersOrdersProducts,它甚至有点有意义——当您在查询中看到 Order_Id 时,您确切地知道 table 它来自什么,你(至少在理论上)永远不需要任何别名 - 但是 - 我正在处理的数据库确实有一些 long-named tables - tables 在他们的名字中有 4、5 和 6 个词 - 所以我开始使用缩写 - 然后你得到像 PMTM_Something_Id 和哎呀这样的东西 - 有window 的可读性——如果你使用整个 table 名称,那就更糟了——我什至没有在谈论 many-to-many 关系的桥梁 table .
我不会再犯那个错误了。

  1. Use SQLDataReader.GetSchemaTable() to write this functionality myself

不要去那里。真的,不要。你只会让自己陷入比现在更糟的境地。

  1. Use a different database connection library

正如我在开头所写的那样 - 这不是 ADO.Net 的问题 - 这是 SQL 的问题 - 所以使用不同的数据库连接库不会解决这个问题。 我不确定 JDBC 是如何工作的,但是可以合理地假设 reader.GetOrdinal(tableName + "." + columnName); 完全按照 reader.GetOrdinal(columnName); 的方式进行操作。检查一下会很有趣,但是我最后一次在 Java 中写任何东西实际上是在上个千年 - 所以我什至不打算尝试。

我有点同意 Zohar 关于列别名的看法。

根据您的查询编写方式以及您对编码语言的熟悉程度,编写一个相对简单的实用程序(例如,c#)可能是可行的,它可以将您的原始 sql查询,自动添加需要的列别名,输出到另一个window ?

然后您的代码可以只使用具有所需列别名的查询。