【问题标题】:C# Generating new id from database on windows forms applicationC#从Windows窗体应用程序的数据库中生成新ID
【发布时间】:2017-12-31 09:27:46
【问题描述】:

我必须在我的加载窗口表单应用程序上自动生成新的 AccountID。

因此,例如,当用户在“帐户 ID”的文本框中启动 Windows 窗体“添加新帐户”时,我必须显示数据库中的最新值。如果我在 Windows 窗体中的数据库中有两个帐户,则文本框中的值将是三个。

如果我在数据库中至少有一个帐户,我的代码可以完美运行,但是当我的数据库为空时,我得到了异常。

这是我的代码:

public int GetLatestAccountID() 
{
    try
    {
        command.CommandText = "select Max(AccountID)as maxID from Account";
        command.CommandType = CommandType.Text;

        connection.Open();

        OleDbDataReader reader= command.ExecuteReader();

        if (reader.Read())
        {
            int valueID = Convert.ToInt32(reader["maxID"]);
            return valueID + 1;
        }

        return 1;
    }
    catch (Exception ex)
    {
        throw ex;
    }
    finally
    {
        if (connection!= null)
        {
            connection.Close();
        }
    }
}

我也在stackoverflow上找到答案:

object aa = DBNull.Value;
int valueID = (aa as int?).GetValueOrDefault(); 

但是如果我的数据库是空的,这行代码就可以工作,但是当我在数据库中有一个帐户时,它总是会显示在我的 windows 窗体中的帐户 id 文本框值 1 中。我使用 Microsoft Access 2007 数据库。

感谢您的帮助。

【问题讨论】:

    标签: c# winforms ms-access-2007


    【解决方案1】:

    你可以像下面这样进一步简化,

    从 Account 中选择 isnull(max(accountID),0) 作为 maxID

    【讨论】:

      【解决方案2】:

      我猜你想要:

      public int GetLatestAccountID(string connectionString) 
      {
          using(var dbConn = new OleDbConnection(connectionString))
          {
              dbConn.Open();
      
              string query = "select Max(AccountID) from Account";
              using(var dbCommand = new OleDbCommand(query, dbConn))
              {
                  var value = dbCommand.ExecuteScalar();
                  if ((value != null) && (value != DBNull.Value))
                      return Convert.ToInt32(value) + 1;
      
                  return 1;
              }
          }
      }
      

      您似乎只打开了一次数据库连接,并在整个程序期间保持打开状态。不要那样做;这会导致竞争条件和数据损坏。 .NET 实现了数据库连接池,因此您根本不会通过保持连接打开来提高性能。

      您也没有告诉我们您使用GetLatestAccountID 的目的。如果您尝试将其用作主键,您还将遇到竞争条件问题。如果你想要一个主键,你应该让数据库创建它并在你创建记录后返回值。

      【讨论】:

      • 已经有一段时间了,但ExecuteScalar 会帮助而不是ExecuteReader
      • 有效!非常感谢!!是的,这是我的主键,但在数据库中我选择的是数字,而不是自动编号。
      • 请注意ExecuteReader 可以正常工作,解决方案是if (value != DBNull.Value)。此外,您应该对主键使用自动编号,而不是 Max(anything)
      【解决方案3】:
      public int GetLatestAccountID() 
      {
          try
          {
              int accounts = 0;
      
              command.CommandText = "select Max(AccountID)as maxID from Account";
              command.CommandType = CommandType.Text;
      
              connection.Open();
      
              OleDbDataReader reader= command.ExecuteReader();
      
              if (reader.Read())
              {
                  accounts = Convert.ToInt32(reader["maxID"]) + 1;
              }
      
              return accounts;
          }
          catch (Exception ex)
          {
              throw ex;
          }
          finally
          {
              if (connection!= null)
              {
                  connection.Close();
              }
          }
      }
      

      【讨论】:

      • 我尝试过,但它也不起作用。解决方案是使用 Execute Scalar 而不是 Execute Reader。感谢您的回复并试图帮助我。
      • 问题不是ExecuteReader,而是Convert.ToInt32(reader["maxID"]) 不适用于可空列。
      【解决方案4】:

      你能用 SELECT COUNT(column_name) FROM table_name;计算帐户数量而不是选择哪个帐户最大?

      【讨论】:

      • 是的,但如果我的数据库为空,它也不起作用。解决方案是使用:Execute Scalar not Execute Reader
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-31
      • 1970-01-01
      • 1970-01-01
      • 2010-11-24
      相关资源
      最近更新 更多