5

我有一张存储被拒绝的合同提案的表格。

CREATE TABLE "STATUS_CONTRATO" (
  "STC_ID" NUMBER NOT NULL,
  "CTB_CONTRATO" NUMBER NOT NULL,
  "STC_DATA" DATE NOT NULL,
  "STC_OBSERVACAO" VARCHAR2(200) NOT NULL,
  CONSTRAINT "STATUS_CONTRATO_PK" 
    PRIMARY KEY ( "STC_ID") 
    ENABLE 
    VALIDATE,
  CONSTRAINT "FK_CONTRATO" 
    FOREIGN KEY ( "CTB_CONTRATO")
       REFERENCES "CONTRATO" ( CTB_CONTRATO) 
       ON DELETE SET NULL 
    ENABLE 
    VALIDATE)
;

(由 Visual Studio 2010 生成的脚本)

该表有一个简单的触发器,其中设置了 的值STC_ID

TRIGGER "STATUS_CONTRATO_TRIGGER1"
  BEFORE
  INSERT
  ON "STATUS_CONTRATO"
  FOR EACH ROW

when (new.STC_ID = 0)
DECLARE
BEGIN 
  SELECT SEQ_STATUS_ID.NEXTVAL INTO :NEW.STC_ID FROM DUAL;
END;

SEQ_STATUS_ID是一个简单的序列。

这是我的问题:

我可以在 VS2010 查询窗口中成功执行此插入:

insert into myschema.STATUS_CONTRATO s(
  s.STC_ID, s.CTB_CONTRATO, s.STC_DATA, s.STC_OBSERVACAO
)values(
  0, 10, SYSDATE, 'Inserting by hand works'
);

但是,当我尝试使用 EF 插入时,我得到了这个异常:

System.Data.UpdateException: An error occurred while updating the entries. 
See the inner exception for details. ---> Oracle.DataAccess.Client.OracleException: 
ORA-01400: cannot insert NULL into ("MYSCHEMA"."STATUS_CONTRATO"."STC_ID")
ORA-06512: at line 4

我正在使用此代码插入

STATUS_CONTRATO statusContrato = new STATUS_CONTRATO() {
    STC_ID = 0,
    CTB_CONTRATO = codContrato,
    STC_DATA = DateTime.Today,
    STC_OBSERVACAO = observacao
};
ent.STATUS_CONTRATO.AddObject(statusContrato);
ent.SaveChanges();

我正在使用 VS2010、Oracle 11g(CentOS 服务器)、ODP.NET 客户端 11.2.0.3.0 生产、.NET Framework 4.0、EF 4。

4

3 回答 3

4

检查这个:http ://www.oracle.com/technetwork/issue-archive/2011/11-sep/o51odt-453447.html

特别是“触发器和序列”部分

从工具菜单中,选择运行 SQL Plus 脚本。浏览到提取代码和脚本的位置,选择 triggers.sql 脚本,从列表中选择 HR 连接,然后单击 Run。每当为该值传入 NULL 时,脚本创建的 INSERTEMPLOYEES 触发器就会为 EMPLOYEE_ID 生成一个新序列........

于 2012-08-15T16:25:22.397 回答
1

你的代码有效,除了一个问题

ent.UNV_STATUS_CONTRATO.AddObject(statusContrato);

UNV_STATUS_CONTRATO另一张桌子吗?为什么不是

ent.STATUS_CONTRATO.AddObject(statusContrato);

那应该工作得很好。

但是,您可能会发现最好从代码中获取序列值并将其应用到内存中的 ID 列,然后再保存更改。所以是这样的:

    public static int GetSequenceNextVal()
    {
        using (YourEntities entities = new YourEntities ())
        {
            var sql = "select myschema.SEQ_STATUS_ID.NEXTVAL from dual";
            var qry = entities.ExecuteStoreQuery<decimal>(sql);
            return (int)qry.First();
        }
    }

然后你之前调用那个方法SaveChanges()

就个人而言,我更喜欢以这种方式处理它,以便我的内存中实体也具有正确的 ID,而不是只有 0,或者必须立即查询它等等。

此外,这里描述的触发器和序列下的方法可以将实体的 PK 连接到序列。

于 2012-08-15T16:25:45.257 回答
0

您需要在 EF 映射中指定数据库不会为您生成密钥,并且 EF 应该使用您提供的密钥...

在以下线程中查看我的帖子: https ://stackoverflow.com/a/18635325/1712367

于 2013-09-05T11:50:08.097 回答