【问题标题】:Is there a way to use fully qualified sql column names in ado .net?有没有办法在 ado .net 中使用完全限定的 sql 列名?
【发布时间】:2020-12-28 17:58:59
【问题描述】:

我正在使用我的 .net Web API 连接一个数据库(大约 30 个表)。 现在我使用以下代码:

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

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

想过但不想用的东西:

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

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

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

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

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

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

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

Ado.Net 被广泛使用,我主要使用许多人使用的库,因为它们更易于维护 - 如果我对它们有问题,几乎可以肯定互联网上的 100 个人也有同样的问题,并且有博客文章讨论解决方案。如果 ado.net 中没有干净的方法,我会切换图书馆。

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

因此这里是我的结果问题:

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

【问题讨论】:

    标签: sql sql-server .net-core ado.net


    【解决方案1】:

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

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

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

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

    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
    

    想过但不想用的东西:

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

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

    1. 更改数据库以在整个数据库中具有唯一的列名

    这似乎是一个可以接受的想法,但很快就会变得相当麻烦。
    我曾经设计过一个数据库,它的所有列都以包含表的名称为前缀。
    当您有 UsersOrdersProducts 之类的表时,这很容易,而且它甚至有点道理 - 当您在查询中看到 Order_Id 时,您确切地知道它来自哪个表并且您(至少在理论)永远不需要给任何东西起别名 - 然而 - 我正在处理的数据库有一些非常长的名称表 - 名称中包含 4、5 和 6 个单词的表 - 所以我开始使用缩写 - 然后你会得到像 PMTM_Something_Id 和 oops 这样的东西 - 可读性已经超出了窗口 - 如果你使用整个表名,那就更糟糕了 - 我什至没有谈论多对的桥接表-许多关系。
    我不会再犯这个错误了。

    1. 使用 SQLDataReader.GetSchemaTable() 自己编写此功能

    不要去那里。真的,不要。你只会让自己陷入比现在更大的混乱。

    1. 使用不同的数据库连接库

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

    【讨论】:

      【解决方案2】:

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

      根据您的查询编写方式以及您对编码语言的熟悉程度,编写一个相对简单的实用程序(例如 c#)可能是可行的,该实用程序可以将原始 sql 查询作为输入,自动添加所需的列别名,并在另一个窗口中输出?

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

      【讨论】:

      • 这可能不像您想象的那么容易。当然,在selectfrom 之前吃任何东西。子查询呢?常用表表达式?按子句排序?解析 sql 并不像乍一看那么简单。
      猜你喜欢
      • 1970-01-01
      • 2019-03-13
      • 2018-07-19
      • 1970-01-01
      • 2011-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多