【问题标题】:Check if a column exists while reading a database in C#在 C# 中读取数据库时检查列是否存在
【发布时间】:2018-10-27 06:08:34
【问题描述】:

在我的数据库中,我为对象创建了两个不同的表,比如说 OBJECT 和 ORIGINAL_OBJECT(在法语中,例如它是 Repere),它们之间的唯一区别是 ORIGINAL_OBJECT 没有任何列用于保存所做的修改。

我有一个函数可以获取所有字段:

public Repere Select_detail_repere(string query)
        {
            Repere det = null; ;
            if (this.OpenConnection() == true)
            {
                IDataReader dataReader = ExecuteReader(query);
                while (dataReader.Read())
                {
                    det = new Repere();
                    det.Name = (dataReader["DET_NOM"] ?? string.Empty).ToString().Trim();
                    det.Modifies = dataReader["MODIFICATIONS"].ToString().Trim();
                    det.Profil = (dataReader["DET_PRF"] ?? string.Empty).ToString().Trim();
                    det.Matiere = (dataReader["DET_MAT"] ?? string.Empty).ToString().Trim();
                    det.GroupeProfil = (dataReader["DET_GRP_PRF"] ?? string.Empty).ToString().Trim();
                    det.Longueur = double.Parse(dataReader["LONGUEUR"].ToString().Trim());
                    det.Largeur = double.Parse(dataReader["DET_LARGE"].ToString().Trim());
                    det.Hauteur = double.Parse(dataReader["DET_HAUT"].ToString().Trim());
                    det.Poids = double.Parse(dataReader["DET_PDS"].ToString().Trim());
                    det.Angle1 = double.Parse(dataReader["ANG_AME_1"].ToString().Trim());
                    det.Angle2 = double.Parse(dataReader["ANG_AME_2"].ToString().Trim());
                    det.AngleAile1 = double.Parse(dataReader["ANG_AILE_1"].ToString().Trim());
                    det.AngleAile2 = double.Parse(dataReader["ANG_AILE_2"].ToString().Trim());
                    det.PercageString = (dataReader["PERCAGE"] ?? string.Empty).ToString().Trim();
                    det.ScribingString = (dataReader["SCRIBING"] ?? string.Empty).ToString().Trim();
                    det.Mark = (dataReader["MARK"] ?? string.Empty).ToString().Trim();
                    det.ContInt0 = (dataReader["CONT_INT"] ?? string.Empty).ToString().Trim();
                    det.ContExt0 = (dataReader["CONT_EXT"] ?? string.Empty).ToString().Trim();
                    det.Revision = (dataReader["REVISION"] ?? string.Empty).ToString().Trim();
                }
                this.CloseConnection();
            }
            return det;
        }

我对 OBJECT 和 OBJECT_ORIGINAL 使用相同的函数。 但是当我想阅读我的 OBJECT_ORIGINAL 时,我遇到了一个错误,指出该字段不存在(显然)。

我已经在其他情况下遇到了同样的问题,因为这个函数只有在我使用SELECT * 时才能工作(如果我没有读取所有列,这将返回错误)。

到目前为止,我发现解决它的唯一方法是使用 try/catch(在 catch 中我将应用默认值,例如 ID=-1),但我觉得这不是一个非常正确的解决方案,并且正在寻找另一种方法来做到这一点。

【问题讨论】:

  • 你读过IDataReader的MSDN文档吗?
  • 刚刚做了,但没有帮助...

标签: c# mysql


【解决方案1】:

您需要检查数据读取器中是否存在 MODIFICATIONS 列,因为您不知道它。

在微软的documentation中,我发现了一个叫做GetSchemaTable的方法。
它将为您提供一个描述列元数据的数据表。因此,您可以检查该表以查看是否有名称为 MODIFICATIONS 的列。
我会用另一种方法进行检查,这样它就不会使您的 while 循环中的代码变得那么混乱。

您可以在 StackOverflow Check for column name in a SqlDataReader object 上查看此问题,该问题的解决方案更短。
我认为这甚至是一个更好、更容易的解决方案,但是在我几乎完成了上面的答案之后,我找到了它(通过简单的谷歌搜索)。所以这就是为什么我给你两个解决方案(也帮助你一点我在评论中指出的 MS 文档)

【讨论】:

  • 好的,我想我明白了。使用堆栈链接中给出的方法,我启动方法“HasColumn”(当然只有一次),然后 ifelse 将解决问题。
  • 好吧,关于堆栈链接,我无法理解它是如何工作的。但是,多亏了你,我找到了指向 GetSchemaTable,然后是 DataColumnCollection 的链接,我想我找到了一些东西,它不像我预期的那样“短”,但它成功了,谢谢
【解决方案2】:

提供您使用的查询也会有所帮助,但我认为您可以在查询中使用IF COL_LENGTH('table_name','column_name') IS NOT NULL

【讨论】:

  • 查询非常简单:SELECT * FROM table1 会起作用,SELECT * FROM table2 不起作用,因为“MODIFICATIONS”列不存在。不是在查询中我需要设置一个条件,而是当我读取结果时
【解决方案3】:

您可以使用 mysql 存储过程并对其进行内部检查。 在这里检查。 check if column exists before ALTER TABLE -- mysql

【讨论】:

  • 我已经看到了,这不是我想要的,他在那个帖子上说的是如果它不存在就创建列,我不想碰它。跨度>
  • 啊抱歉没看懂。它安静敏感的数据库操作嗯..
【解决方案4】:

这个问题可以引用为“重复”,我在stack找到了答案

public Repere Select_detail_repere(string query)
{
    Repere det = null; ;
    if (this.OpenConnection() == true)
    {
        IDataReader dataReader = ExecuteReader(query);
        bool containsModification = CheckIfDataContains(dataReader, "MODIFICATIONS");
        while (dataReader.Read())
        {
            det = new Repere();
            det.Name = (dataReader["DET_NOM"] ?? string.Empty).ToString().Trim();
            if(containsModification)
            {
                 det.Modifies = dataReader["MODIFICATIONS"].ToString().Trim();
            }
            else
            {
                 det.Modifies = "";
            }
            det.Profil = (dataReader["DET_PRF"] ?? string.Empty).ToString().Trim();
            det.Matiere = (dataReader["DET_MAT"] ?? string.Empty).ToString().Trim();
            ...
         }
         this.CloseConnection();
      }
      return det;
  }
  public bool CheckIfDataContains(IDataReader dataReader,string columnName)
    {
        for (int i = 0; i < dataReader.FieldCount; i++)
        {
            if (dataReader.GetName(i).Equals(columnName, StringComparison.InvariantCultureIgnoreCase))
            return true;
        }
        return false;
    }

【讨论】:

  • 我觉得不错。不是使用for 循环,而是使用遍历所有列的contains 方法。您可以通过只执行 return columns.Contains(columnName) 而不是 if 语句来缩短方法,但这正是您喜欢的。
  • 谢谢,其实return columns.Contains(columnName) 更好,刚刚编辑,感谢您的反馈。 p.S:你如何“灰色”你的 cmets?
  • 您可以为此使用反引号,请参阅stackoverflow.com/editing-help#code 以获取有关格式化的帮助。
  • 好吧,只是“不被接受”的答案,因为我现在才注意到代码不起作用,实际上 {columns.Contains(columnName)} 总是返回 false
  • Contains 可能区分大小写。还要确保列名不重复,它将返回 false。请参阅 Microsoft 文档
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-26
  • 1970-01-01
  • 2015-06-18
  • 1970-01-01
  • 1970-01-01
  • 2021-12-11
  • 1970-01-01
相关资源
最近更新 更多