C#에서 저장 프로시저를 큰 CLOB로 호출하는 문제 발생
제가 이러한 문제를 처음 겪는 것은 아니며, 아래에 몇 가지 참조 게시물을 나열하겠지만, 여전히 적절한 해결책을 찾고 있습니다.
C# 웹 서비스에서 저장 프로시저(Oracle 10g 데이터베이스)를 호출해야 합니다.웹 서버에 Oracle 9i 클라이언트가 설치되어 있으며 Microsoft를 사용하고 있습니다.System.Data.OracleClient
.
이 절차에서는 XML을 CLOB로 사용합니다.XML이 4,000바이트 이상일 때(일반적인 사용 사례일 가능성이 높음) 다음 오류가 발생했습니다.
ORA-01460 - 구현되지 않았거나 불합리한 변환 요청
또한 저장 프로시저를 C#에서 직접 호출하지 않고 익명 PL/SQL 코드를 정의하는 유망한 해결 방법을 찾았습니다.이 코드는 Oracle Command로 실행됩니다.XML은 문자열 리터럴로 포함되며 프로시저 호출은 해당 코드 조각 내에서 수행됩니다.
private const string LoadXml =
"DECLARE " +
" MyXML CLOB; " +
" iStatus INTEGER; " +
" sErrMessage VARCHAR2(2000); " +
"BEGIN " +
" MyXML := '{0}'; " +
" iStatus := LoadXML(MyXML, sErrMessage); " +
" DBMS_OUTPUT.ENABLE(buffer_size => NULL); " +
" DBMS_OUTPUT.PUT_LINE(iStatus || ',' || sErrMessage); " +
"END;";
OracleCommand oraCommand = new OracleCommand(
string.Format(LoadXml, xml), oraConnection);
oraCommand.ExecuteNonQuery();
안타깝게도 XML이 32KB 이상이 되면 이 접근 방식이 실패합니다. 이는 여전히 제 애플리케이션에서 가능성이 높습니다.이번 오류는 다음과 같은 PL/SQL 컴파일러에서 발생합니다.
ORA-06550: 1행, 87열: PLS-00172: 문자열 리터럴이 너무 깁니다.
몇 가지 조사 후에 저는 제 두 번째 접근법으로는 문제를 해결할 수 없다는 결론을 내렸습니다.
위에서 언급한 게시물에 이어 다음 두 가지 옵션이 있습니다.
- ODP.NET으로 전환합니다(Microsoft에서 사용되지 않는 DB 클라이언트의 버그로 간주되므로)
- CLOB를 테이블에 삽입하고 저장된 프로시저를 테이블에서 읽습니다.
(첫 번째 게시물에는 일부 고객이 버그가 있다고 했지만, 내 고객(9i)은 언급된 10g/11g 버전 범위에 해당하지 않습니다.)
당신은 이것들이 유일하게 남은 두 가지 옵션인지 확인할 수 있습니까?아니면 저를 도와줄 다른 방법이 있나요?
XML은 결국 어떤 테이블에도 저장되지 않지만 XML 내용을 기반으로 일부 테이블에 레코드를 삽입하는 저장 프로시저에 의해 처리됩니다.
두 가지 옵션에 대한 고려 사항:
- ODP.NET으로 전환하는 것은 지금까지 시스템 액세스 권한이 없는 웹 서버에 설치해야 하고 클라이언트에 코드를 배포해야 할 수도 있기 때문에 각 클라이언트가 배포의 일부로 ODP.NET을 설치해야 할 수도 있기 때문입니다.
- 테이블을 우회하면 클라이언트 코드가 상당히 복잡해지고 데이터베이스가 PL/SQL 루틴을 조정/확장하는 데 상당한 노력이 소요됩니다.
저는 그 문제를 해결할 다른 방법이 있다는 것을 발견했습니다!동료 직원이 이 블로그를 가리키며 저의 하루를 저장했습니다. 이 블로그에는 다음과 같은 내용이 블로그는 다음과 같습니다.
BeginTransaction이 DbConnection에서 이미 호출된 경우 매개 변수 값을 설정합니다.
더 간단한 방법이 있을까요?이 블로그는 다음과 관련이 있습니다.Oracle.DataAccess
하지만 그것도 마찬가지로 효과가 있습니다.System.Data.OracleClient
.
실제로 이는 다음을 의미합니다.
varcmd = new OracleCommand("LoadXML", _oracleConnection);
cmd.CommandType = CommandType.StoredProcedure;
var xmlParam = new OracleParameter("XMLFile", OracleType.Clob);
cmd.Parameters.Add(xmlParam);
// DO NOT assign the parameter value yet in this place
cmd.Transaction = _oracleConnection.BeginTransaction();
try
{
// Assign value here, AFTER starting the TX
xmlParam.Value = xmlWithWayMoreThan4000Characters;
cmd.ExecuteNonQuery();
cmd.Transaction.Commit();
}
catch (OracleException)
{
cmd.Transaction.Rollback();
}
저의 경우, 치코도로의 해결책은 효과가 없었습니다.ODPODP)을 .NET을 사용하고 있습니다.Oracle.DataAccess
).
나를 위한 솔루션은 다음과 같습니다.OracleClob
물건.
OracleCommand cmd = new OracleCommand("LoadXML", _oracleConnection);
cmd.CommandType = CommandType.StoredProcedure;
OracleParameter xmlParam = new OracleParameter("XMLFile", OracleType.Clob);
cmd.Parameters.Add(xmlParam);
//connection should be open!
OracleClob clob = new OracleClob(_oracleConnection);
// xmlData: a string with way more than 4000 chars
clob.Write(xmlData.ToArray(),0,xmlData.Length);
xmlParam.Value = clob;
try
{
cmd.ExecuteNonQuery();
}
catch (OracleException e)
{
}
저는 당신이 싼 포인트를 얻기 위해 이것을 구글에 검색한 것 같습니다. 하지만 여기에 훌륭한 설명이 있습니다.
http://www.orafaq.com/forum/t/48485/0/
기본적으로 문자열 리터럴에는 4000자를 초과할 수 없으며, 추가 작업이 필요한 경우 저장 프로시저를 사용해야 합니다.그러면 최대 32KB로 제한되므로 삽입을 "청크"해야 합니다.블레치.
-오이신
치코도로의 말이 맞습니다.
public static int RunProcedure(string storedProcName, IDataParameter[] parameters)
{
using (OracleConnection connection = new OracleConnection(connectionString))
{
int rowsAffected;
OracleCommand command = new OracleCommand(storedProcName, connection);
command.CommandText = storedProcName;
command.CommandType = CommandType.StoredProcedure;
foreach (OracleParameter parameter in parameters)
{
command.Parameters.Add(parameter);
}
connection.Open();
try
{
// start transaction
command.Transaction = connection.BeginTransaction();
rowsAffected = command.ExecuteNonQuery();
command.Transaction.Commit();
}
catch (System.Exception ex)
{
command.Transaction.Rollback();
throw ex;
}
connection.Close();
return rowsAffected;
}
}
언급URL : https://stackoverflow.com/questions/3557995/issues-calling-stored-procedure-from-c-sharp-with-large-clob
'source' 카테고리의 다른 글
테이블 값 함수 실행 방법 (0) | 2023.06.28 |
---|---|
SQLAlchemy ORM을 Panda DataFrame으로 변환 (0) | 2023.06.28 |
Mariadb: OFFSET 및 LIMIT를 사용하는 페이지가 한 행을 건너뜁니다. (0) | 2023.06.28 |
2개의 열을 기준으로 SQL 고유 제약 조건을 만들려면 어떻게 해야 합니까? (0) | 2023.06.23 |
WiX에서 Oracle ODP.Net에 대한 레지스트리 키(값이 아님)가 있는지 테스트하려면 어떻게 해야 합니까? (0) | 2023.06.23 |