C# 为什么ExecuteOnQuery捕获异常{“列\“ORGTABLE\”的验证错误\“FIKEYID\”,值\“*null*\”}

C# 为什么ExecuteOnQuery捕获异常{“列\“ORGTABLE\”的验证错误\“FIKEYID\”,值\“*null*\”},c#,ado.net,firebird,firebird-embedded,C#,Ado.net,Firebird,Firebird Embedded,为什么ExecuteOnQuery捕获异常{列\ORGTABLE\的验证错误。\FIKEYID\,值\*null*\} 字段定义如下: fstPriority VARCHAR(30), fstInfo VARCHAR(100), fstDateCreated VARCHAR(30), fstDateModified VARCHAR(30), fiKeyID INTEGER PRIMARY KEY 在守则的这一节中: stFieldNamesNoKeyId = "fstPriority, fst

为什么ExecuteOnQuery捕获异常{列\ORGTABLE\的验证错误。\FIKEYID\,值\*null*\}

字段定义如下:

fstPriority VARCHAR(30), fstInfo VARCHAR(100), fstDateCreated VARCHAR(30), fstDateModified VARCHAR(30), fiKeyID INTEGER PRIMARY KEY
在守则的这一节中:

stFieldNamesNoKeyId = "fstPriority, fstInfo, fstDateCreated, fstDateModified".

stValuesPlaceHolder = "@p0, @p1, @p2, @p3"
四 fbCmd.Parameters.AddWithValue:

stPlaceHolder = "@p0" ... stValue = "1st value";

stPlaceHolder = "@p1" ... stValue = "2nd value";

stPlaceHolder = "@p2" ... stValue = "3rd value";

stPlaceHolder = "@p3" ... stValue = "4th value";
我没有为fiKeyID添加值,因为它是主键

我没有为fiKeyID添加值,因为它是主键

所以您尝试插入一个空主键。这是不允许的

主键中永远不允许为空。如果列在列定义或域定义中被定义为非空,则该列只能是PK的一部分

然后,您可能希望请求服务器自动生成ID。做这件事的方法很少

例如,Firebird 3带有auto inc列类型。这是对数据库开发人员以前显式使用的工具的一种语法糖分

Firebird 2和以前的版本使用SQL序列来实现它

如果ID字段为空,则必须在表上执行BEFORE-INSERT或BEFORE-INSERT或UPDATE触发器,以填充生成器中的ID字段

在这里,它可以归结为您的SQL access库。 因为通常在插入行之后,您必须知道它的ID

如果您不关心新生儿行的ID,您可以跳过其余部分

但是,如果您想同时插入行和知道行的ID,那么可以归结为另一种选择

低技术的纯SQL库会迫使您进行双重旅行:

从RDB$数据库中选择GEN_IDGEN_T1_ID,1或从RDB$数据库中选择GEN_T1_ID的下一个值将为您保留一个免费令牌,然后您将显式地将ID PK列分配给该值,并将其与数据列一起插入,从而绕过触发器

或者使用高级SQL库,您可以要求Firebird自动计算值并向您报告:插入tablenamedata1、data2、dataq3值1、2、3返回id。请参阅

您是否需要了解插入的ID,以及您的SQL库是否支持INSERT-RETURNING命令—由您决定

然而,当我在谷歌搜索时,它是www.Google.com,它提供了许多关于C Firebird Insert Returniung的链接,用于许多不同的C SQL库,同样,只有你才能知道你使用的是哪一个。对于来自不同LIB的几个示例:

等等定义:

public const string stMAIN_TABLE_NAME = " OrgTable ";
public const string stDELETED_TABLE_NAME = "  BackupTable ";

public const string stFIELD_DEFINITIONS = " fstPriority VARCHAR(30)" + 
                                          ", fstInfo VARCHAR(100)" +
                                          ", fstDateCreated VARCHAR(30)" +
                                          ", fstDateModified VARCHAR(30)" +
                                          ", fiKeyID INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY ";

public const string stFIELD_NAMES_NO_KEY_ID = " fstPriority" + 
                                              ", fstInfo" + 
                                              ", fstDateCreated" + 
                                              ", fstDateModified ";

public const string stFIELD_NAMES_KEY_ID = " fiKeyID ";

public const string stFIELD_NAMES = stFIELD_NAMES_NO_KEY_ID + ", " + stFIELD_NAMES_KEY_ID;
代码:


表的DDL是什么,您使用的是哪个Firebird版本。您是否有为您生成ID的触发器?否则,不包括主键的值将导致分配null,这是不允许的,因此在这种情况下,异常是正确的。顺便说一句:我想你的意思是为什么ExecuteOnQuery抛出异常。你可以只使用SQL进行插入吗?如果不是,我怀疑问题在于关键字段-在SQL server中,它通常会设置为identity,并具有种子和增量值1Firebird ADO.NET。。。FirebirdClient.5.8.0---上述内容已成功用于写入Access.accdb和SQLite。对于Access.accdb,主键由Access.accdb设计器定义。。。对于SQLite,主键定义为整数主键。--生成ID的触发器是什么?Excel/Access Microsoft Jet不是SQL数据库,尽管有一些桥可以使用部分SQL从中获取数据。SQLite有一种非标准的行为,即每一行都有一个专用的ROWID列,不管您是否需要它——adn ur主键会被自动删除并对其进行短路。但我想知道是否有可能备份/恢复SQLite DB或同时连接多台不同计算机的SQLite DB,ROWID列是否仍然可行-我可以添加返回id,-FbCommand fbCmd=new fbcommandsert。。。返回+id+,fbConn,fbTransaction-但是我不确定fbCmd.Parameters.AddWithValue应该使用什么-我是否添加stPlaceHolder=@p5。。。stValue=。@ttom我对C几乎一无所知,我猜你必须联系DotNetProvider论坛或使用insert搜索C代码片段。我告诉你在Firebird中通常是如何实现的,但我不知道C FB库有多好或有多坏。还要试着学习如何在C中调用诸如EXECUTE BLOCK或调用存储过程之类的语句。FB API级别INSERT-RETURNING上的原因被分类为SP调用类型的语句。也许这也是他们在DotNetProviderAPI上公开的方式。也许我也猜错了,返回时没有括号。现在修正我的答案答案答案的功劳属于马克·罗特维尔。。。看见
stPlaceHolder = "@p0" ... stValue = "1st value";

stPlaceHolder = "@p1" ... stValue = "2nd value";

stPlaceHolder = "@p2" ... stValue = "3rd value";

stPlaceHolder = "@p3" ... stValue = "4th value";
CREATE GENERATOR gen_t1_id;
SET GENERATOR gen_t1_id TO 0;
set term !! ;
 CREATE TRIGGER T1_BI FOR T1
 ACTIVE BEFORE INSERT POSITION 0
 AS
 BEGIN
 if (NEW.ID is NULL) then NEW.ID = GEN_ID(GEN_T1_ID, 1);
 END!!
set term ; !!
public const string stMAIN_TABLE_NAME = " OrgTable ";
public const string stDELETED_TABLE_NAME = "  BackupTable ";

public const string stFIELD_DEFINITIONS = " fstPriority VARCHAR(30)" + 
                                          ", fstInfo VARCHAR(100)" +
                                          ", fstDateCreated VARCHAR(30)" +
                                          ", fstDateModified VARCHAR(30)" +
                                          ", fiKeyID INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY ";

public const string stFIELD_NAMES_NO_KEY_ID = " fstPriority" + 
                                              ", fstInfo" + 
                                              ", fstDateCreated" + 
                                              ", fstDateModified ";

public const string stFIELD_NAMES_KEY_ID = " fiKeyID ";

public const string stFIELD_NAMES = stFIELD_NAMES_NO_KEY_ID + ", " + stFIELD_NAMES_KEY_ID;
//------------------------------
static private bool boCreateDatabaseTables(string stPathFilename, 
                                           string stUserID, 
                                           string stPassword, 
                                           List<string> liststTableNames, 
                                           List<string> liststFieldDefinitions) 
{
  bool boErrorFlag = false;
  int iTablesCount = liststTableNames.Count();
  string stOpenConn = new FbConnectionStringBuilder {
    Database = stPathFilename,
    UserID = stUserID,
    Password = stPassword,
    ServerType = FbServerType.Embedded,
    ClientLibrary = stCLIENT_LIBRARY
    }.ToString();
  using (FbConnection fbConn = new FbConnection(stOpenConn)) {
    try {
      fbConn.Open();

      FbTransaction fbTransaction = fbConn.BeginTransaction();
      for (int ii = 0; ii < iTablesCount; ii++) {
        string stSql = "CREATE TABLE " + liststTableNames[ii] + "( " + liststFieldDefinitions[ii] + ")";
        FbCommand fbCmd = new FbCommand(stSql, fbConn, fbTransaction);
        fbCmd.ExecuteNonQuery();
      }
      fbTransaction.Commit();
    }
    catch (Exception ex) {
      boErrorFlag = true;
      MessageBox.Show("catch ... GlobalsFirebird ... boCreateDatabaseTables ... " + ex.Message);
    }
}
return boErrorFlag;
}//boCreateDatabaseTables
//------------------------------
//------------------------------
static public bool boAddRow(string stPathFilename,
                            string stUserID,
                            string stPassword,
                            string stTableName,
                            string stFieldNamesNoKeyId,
                            string stFieldNamesKeyId,
                            List<string> liststFieldValuesNoKeyId) 
{
  bool boErrorFlag = false;
  string stOpenConn = new FbConnectionStringBuilder {
    Database = stPathFilename,
    UserID = stUserID,
    Password = stPassword,
    ServerType = FbServerType.Embedded,
    ClientLibrary = stCLIENT_LIBRARY
  }.ToString();

  using(FbConnection fbConn = new FbConnection(stOpenConn)) {
    fbConn.Open();
    try {
      string stValuesPlaceHolder = "@p0";
      for (int iii = 1; iii < liststFieldValuesNoKeyId.Count; iii++)
        stValuesPlaceHolder += ", @p" + (iii).ToString();
      FbTransaction fbTransaction = fbConn.BeginTransaction();
      string stCmd = "INSERT INTO " + stTableName + "(" + stFieldNamesNoKeyId + ") VALUES ( " + stValuesPlaceHolder + " ) RETURNING  " + stFieldNamesKeyId;
      FbCommand fbCmd = new FbCommand(stCmd, fbConn, fbTransaction);

      for (int iii = 0; iii < liststFieldValuesNoKeyId.Count; iii++) {
        string stPlaceHolder = "@p" + (iii).ToString();
        string stValue = liststFieldValuesNoKeyId[iii];
        fbCmd.Parameters.AddWithValue(stPlaceHolder, stValue);
      }
      fbCmd.Parameters.Add(new FbParameter() { Direction = System.Data.ParameterDirection.Output });
      fbCmd.ExecuteNonQuery();
      fbTransaction.Commit();
    }
    catch (Exception ex) {
      boErrorFlag = true;
      MessageBox.Show("catch ... GlobalsFirebird ... boAddRow ... " + ex.Message);
    }
  }
  return boErrorFlag;
}//boAddRow
//------------------------------