【问题标题】:Why am I getting, "A column ID occurred more than once in the specification"?为什么我会收到“规范中多次出现列 ID”?
【发布时间】:2013-03-30 05:26:53
【问题描述】:

如果表不存在,我有代码创建表并添加所有必要的列,但对于用户拥有旧版本表的情况,它会添加一些新的

列。然而,当第二个条件为真并且添加列的 DDL 运行时,我得到“一个列 ID 在规范中出现了不止一次”

这里是代码,以及确定表和列是否存在的辅助函数:

    bool tableExists = dbconn.isValidTable(tablename) != -1;
    if (!tableExists) 
    {
        ddl = "CREATE TABLE Bla (. . . salvationID nvarchar(19), salvation float, discount float)";
        dbconn.DBCommand(ddl, false);
    }
    else // (the table does exist) 
    {
        if(!dbconn.isValidField(tablename,"redemptionID"))
        {
            ddl = string.Format("ALTER TABLE {0} ADD redemptionID nvarchar(19) ", tablename);
            dbconn.DBCommand(ddl,false);
            . . .

        public int isValidTable(string tableName)
        {
            int validTable = -1;
            string tblQuery = string.Format("SELECT COUNT(*) FROM {0}", tableName);
            checkConnection();
            try
            {
                SqlCeCommand cmd = objCon.CreateCommand();
                cmd.CommandText = tblQuery;
                object objcnt = cmd.ExecuteScalar();
                validTable = Int32.Parse(objcnt.ToString());
            }
            catch
            {
                validTable = -1;
            }
            return validTable;
        }

//This has been beautified/elegantized thanks to p.s.w.g at http://stackoverflow.com/questions/15693639/how-can-i-determine-whether-a-column-exists-in-a-sql-server-ce-table-with-c
        public bool isValidField(string tableName, string columnName)
        {
            bool retVal;
            string tblQuery = "SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND 

COLUMN_NAME = @columnName";
            checkConnection();
            try
            {
                SqlCeCommand cmd = objCon.CreateCommand();
                cmd.CommandText = tblQuery;
                SqlCeParameter tblNameParam = new SqlCeParameter("@tableName", SqlDbType.NVarChar, 128);
                tblNameParam.Value = tableName;
                cmd.Parameters.Add(tblNameParam);
                SqlCeParameter colNameParam = new SqlCeParameter("@columnName", SqlDbType.NVarChar, 128);
                colNameParam.Value = tableName;
                cmd.Parameters.Add(colNameParam);
                object objvalid = cmd.ExecuteScalar();
                retVal = !Convert.IsDBNull(objvalid);
            }
            catch
            {
                retVal = false; 
            }
            return retVal;
        }

【问题讨论】:

  • 您能否具体说明代码的哪一部分引发了错误?我不确定您所说的“第二个条件”是什么意思。此外,为简洁起见,您似乎删除了一些 SQL。如果您询问有关 SQL 错误的问题,请包括所有 sql。
  • 第二个条件是else块。问题在于正在运行的 ALTER TABLE ddl - 当它运行时,我在帖子标题中收到错误消息。如果这是真的 - 该列已经存在,为什么它会通过“无效字段”条件?
  • 尝试在retVal = !Convert.IsDBNull(objvalid); 设置一个断点,并确保它根据它的值返回您所期望的值。
  • 我不能在这个项目中使用断点 - 我必须使用 MessageBox.Show() 并将 msgs 写入文件。
  • 因为这是一个 Windows CE 应用程序,必须在设备或模拟器上运行,并且由于我使用的软件版本过时,我必须在 XPMode 虚拟机中使用 VS2003 进行开发和.NET 1.1。我的辛苦死了。已详细记录在其他 SO 职位上; “读者文摘”版本:在调试方面,我陷入了我们曾祖父的史前和过时的方式。

标签: c# sql compact-framework sql-server-ce windows-ce


【解决方案1】:

我怀疑正在发生的事情是isValidField() 正在引发异常,而您的捕获只是在说明该字段不存在时吞下它......当它可能存在时。

我强烈建议您不要只是吞下它,而是实际显示该消息,以便您知道发生了什么。

例如:

public bool isValidField(string tableName, string columnName)
{
    bool retVal;
    string tblQuery = "SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tableName AND COLUMN_NAME = @columnName";
    checkConnection();
    try
    {
        SqlCeCommand cmd = objCon.CreateCommand();
        cmd.CommandText = tblQuery;
        SqlCeParameter tblNameParam = new SqlCeParameter("@tableName", SqlDbType.NVarChar, 128);
        tblNameParam.Value = tableName;
        cmd.Parameters.Add(tblNameParam);
        SqlCeParameter colNameParam = new SqlCeParameter("@columnName", SqlDbType.NVarChar, 128);
        colNameParam.Value = tableName;
        cmd.Parameters.Add(colNameParam);
        object objvalid = cmd.ExecuteScalar();
        retVal = !Convert.IsDBNull(objvalid);
    }
    catch(Exception ex)
    {
        MessageBox.Show(ex.Message);
        retVal = false; // <-- wrong answer
    }
    return retVal;
}

此外,该函数不应该是布尔值。你有3个条件:1.存在; 2.不存在; 3. 发生错误。

如果发生错误,您不希望后面的方法认为它找不到它。另外,我会在您验证表存在的地方做同样的事情。

【讨论】:

  • 如果不返回 bool 结果,调用者如何知道尝试添加已存在的列是否是浪费时间?我认为出于实际目的(以及程序员想要处理不切实际的目的),异常可以等同于“它不是有效的列”?
【解决方案2】:

尝试检查DBNull.Value

try
{
  SqlCeCommand cmd = objCon.CreateCommand();
  cmd.CommandText = tblQuery;
  object objcnt = cmd.ExecuteScalar();
  if ((objcnt != null) && (objcnt != DBNull.Value)) {
    validTable = Int32.Parse(objcnt.ToString());
  } else {
    MessageBox.Show("NULL returned from CreateCommand. Remove this line.");
  }
}
catch

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-30
    • 2020-10-11
    • 2011-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多