4

Oracle テーブルに 4,000 文字の VARCHAR2 フィールドを作成しました。Visual Studio 2010、.NET Framework 4、 ODAC 11.2 Release 4、および Oracle Developer Tools for Visual Studio (11.2.0.3.0)で LINQ to Entities を使用してフィールドに文字列値を挿入しています。1,999 文字を超える文字列値を挿入しようとすると、次の内部例外が発生します。

Oracle.DataAccess.Client.OracleException

ORA-00932: 一貫性のないデータ型: 予期される - NCLOB を取得しました

ただし、SQL Developerを使用すると、問題なく4,000文字の文字列値をフィールドに挿入できます。

XMLTYPE フィールドに保存するときに 2,000 文字の制限がある既知の ODAC バグ(ソース #2 ) がありますが、私は XMLTYPE フィールドに保存していません。GAC に Oracle.DataAccess 2.112.3.0 があり、前述の Oracle ソフトウェアのリリース 5 (11.2.0.3.20) に更新することを検討しましたが、「Oracle Developer Tools for Visual Studio」だけが更新されたように見えるコンポーネントです。はリリース 4 から更新されており、「Oracle Data Provider for .NET 4」が更新が必要なコンポーネントであると考えています。私の .NET プロジェクトでは、System.Data.Entity と System.Data.OracleClient はどちらもランタイム バージョン 4.0.30319 です。

とにかく、他の誰かがこのエラーに遭遇したかどうか、そしてもしそうなら、解決策が見つかったかどうか疑問に思っています. Google によると、XMLTYPE フィールドを操作しているときにのみこのエラーが発生しているとのことですが、VARCHAR2 フィールドを操作しているときにこのエラーが発生するのは私だけではないでしょうか?

(FWIW、上記のリンクにある Oracle フォーラム スレッドのユーザー「997340」としての私の投稿への応答を受け取ることも望んでいます。有用な応答を受け取った場合は、この点に関する知識を必ず共有します。)

編集:それが役立つ場合、以下は私のコードで失敗している2つのブロックです。違いがあるかどうかを確認するために、最初のブロックをトラブルシューティングするときに 2 番目のブロックを作成しました。文字列値が既に挿入されているかどうかを確認するとき (「if」ステートメント)、および実際に文字列値を挿入するとき (「AddObject」ステートメント) に例外が発生します。

1:

if (!(from q in db.MSG_LOG_MESSAGE where q.MESSAGE == msg select q.MESSAGE).Any())
{
  db.MSG_LOG_MESSAGE.AddObject(new MSG_LOG_MESSAGE { MESSAGE = msg });
  db.SaveChanges();
}

2:

if (!db.MSG_LOG_MESSAGE.Any(q => q.MESSAGE == msg))
{
  db.MSG_LOG_MESSAGE.AddObject(new MSG_LOG_MESSAGE { MESSAGE = msg });
  db.SaveChanges();
}

4 月 3 日の更新:

上記の最初のコード ブロックの「if」ステートメントから、Oracle に送信されている SQL をトレースすることができました。ここにあります:

SELECT
CASE WHEN ( EXISTS (SELECT
        1 AS "C1"
        FROM "SEC"."MSG_LOG_MESSAGE" "Extent1"
        WHERE ("Extent1"."MESSAGE" = :p__linq__0)
)) THEN 1 WHEN ( NOT EXISTS (SELECT
        1 AS "C1"
        FROM "SEC"."MSG_LOG_MESSAGE" "Extent2"
        WHERE ("Extent2"."MESSAGE" = :p__linq__0)
)) THEN 0 END AS "C1"
FROM  ( SELECT 1 FROM DUAL ) "SingleRowTable1" ;

残念ながら、私が協力した DBA は「p_linq_0」パラメーターの値を提供してくれませんでしたが、前述のように、1,999 文字を超えると例外が発生します。(この SQL をトレースしたとき、4,000 文字の文字列をパラメーターとして渡しましたが、もちろん例外が発生しました。) DBA は、SQL Plus などの特定の SQL クライアントについて、2,000 文字を超える VARCHAR2 を処理できないことについても言及しました。 . 完全には従いませんでした。SQLを使用するかどうかさらに、SQL Developer、またはその他のツールを使用して、Oracle は引き続き 4,000 文字の VARCHAR2 フィールドを照会します。さらに、私のマジック ナンバーは 1,999 文字です。2,000文字ではありません。DBA は、パラメーターに使用できる文字数に制限があることを意味したのでしょうか? さらに重要なことは、SQL Developer でこの SQL を実行し、パラメーターに 4,000 文字の文字列を入力すると、完全に機能することです。そのため、LINQ to Entities を介して機能しない理由について、私はまだ完全に混乱しています。また、プログラムで次のコードを試して、「msg」変数に 4,000 文字の文字列を指定して同様のクエリを実行しましたが、これも完全に機能しました。

using Oracle.DataAccess;
using Oracle.DataAccess.Client;
using System.Data;

...

OracleConnection conn = new OracleConnection("Data Source=[MASKED];User Id=[MASKED];Password=[MASKED]");
conn.Open();
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT message FROM msg_log_message WHERE message = '" + msg + "'";
cmd.CommandType = CommandType.Text;
OracleDataReader dr = cmd.ExecuteReader();
dr.Read();
string result1 = dr.GetString(0);
conn.Dispose();

今のところ、LINQ to Entities に関連するため、ODAC がバグであることにまだ指を向けています...

4

1 に答える 1