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 接続を選択し、[実行] をクリックします。スクリプトによって作成された INSERTEMPLOYEES トリガーは、その値に NULL が渡されるたびに、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

DBがキーを生成せず、EFが提供したキーを使用する必要があることをEFマッピングで指定する必要があります...

次のスレッドで私の投稿を参照してください: https://stackoverflow.com/a/18635325/1712367

于 2013-09-05T11:50:08.097 に答える