ODP.NET:Oracle.ManagedDataAccess.Client.OracleException (0x80004005):.NET 5(核心)应用程序上的 ORA-01841
ODP.NET: Oracle.ManagedDataAccess.Client.OracleException (0x80004005): ORA-01841 on .NET 5 (Core) application
尝试使用 C# .NET 5 网络应用程序执行 select 和 Oracle.ManagedDataAcces.Client (ODP.NET)。
Oracle.ManagedDataAcces.Client 版本是截至 02/06/2021 的最新版本 3.21.1。
错误:
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware1
An unhandled exception has occurred while executing the request.
Oracle.ManagedDataAccess.Client.OracleException (0x80004005): ORA-01841: (full) year must be between -4713 and +9999, and not be 0
at OracleInternal.ServiceObjects.OracleConnectionImpl.VerifyExecution(Int32& cursorId, Boolean bThrowArrayBindRelatedErrors, SqlStatementType sqlStatementType, Int32 arrayBindCount, OracleException& exceptionForArrayBindDML, Boolean& hasMoreRowsInDB, Boolean bFirstIterationDone)
这是查询码
public async Task<int> GetMyCount(string userName, int THE_YEAR)
{
try
{
string TEST = "STACK_OVERFLOW_TEST";
builder.Clear();
builder.Append($@" SELECT COUNT(*)
FROM {configuration.SCHEMA}.SOME_TABLE CA
INNER JOIN {configuration.SCHEMA}.SOME_OTHER_TABLE CS
ON CS.ID=CA.ID ");
if (viewNotAll)
{
builder.Append($" INNER JOIN {unitOfWork.oracleDbOptions.DBSchemaQP}.ANOTHER_TABLE UT ON CA.SOME_FIELD = UT.SOME_FIELD ");
}
builder.Append(@$" WHERE CA.DATE_TO_FILET BETWEEN TO_DATE(CONCAT('0101', :THE_YEAR),'DDMMYYYY')
AND TO_DATE(CONCAT('3112', :THE_YEAR),'DDMMYYYY') ");
if (TEST == "NO")
builder.Append(" AND CS.TEST_FIELD=0 ");
else
builder.Append(" AND CS.TEST_FIELD=:THE_TEST_FIELD ");
int result = 0;
using (var cmd = unitOfWork.connection.CreateCommand())
{
cmd.Parameters.Add("THE_YEAR", OracleDbType.Int16, 4, THE_YEAR, ParameterDirection.Input);
cmd.Parameters.Add("THE_TEST_FIELD", OracleDbType.Varchar2, 20, userName, ParameterDirection.Input);
cmd.CommandText = builder.ToString();
using (var reader = await cmd.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
result = reader.IsDBNull(0) ? 0 : reader.GetInt32(0);
}
}
return result;
}
}
catch (Exception)
{
throw;
}
}
在 Oracle SQL Developer 或 PL/SQL 中执行查询有效。同样来自 visual studio 服务器 exporer 作品。弹出一个 window 询问参数,类型为 VARCHAR2,它可以很好地执行查询。
我什么都试过了。从 Int16、Int32、VARCHAR2 更改类型以用于测试目的,也基于 Oracle .NET type guide,它指出 Int16 用于长度为 4 的数字,在我的例子中是年份。
没有。
我还尝试使用显示的内容 in this Whosebug question 来检索 SQL 查询历史记录,显然,从外部触发的查询不会被记录。我无法通过此查询找到它们。
唯一有效的方法是直接连接查询中的值:
builder.Append(@$" WHERE CA.SOME_DATE BETWEEN TO_DATE(CONCAT('0101', '{THE_YEAR}'),'DDMMYYYY')
AND TO_DATE(CONCAT('3112', '{THE_YEAR}'),'DDMMYYYY') ");
但是我想使用参数来避免SQL注入。
我做错了什么?
更好用
builder.Append(@$" WHERE CA.DATE_TO_FILET BETWEEN :aDate AND :bDate");
cmd.Parameters.Add("aDate", OracleDbType.Date, ParameterDirection.Input).Value = new DateTime(THE_YEAR, 1, 1);
cmd.Parameters.Add("bDate", OracleDbType.Date, ParameterDirection.Input).Value = new DateTime(THE_YEAR, 12, 31);
CONCAT 连接两个字符串,因此 THE_YEAR 应该是四个字符的字符串而不是整数。你试过了吗
cmd.Parameters.Add("THE_YEAR", OracleDbType.Varchar2, 4, THE_YEAR.ToString(), ParameterDirection.Input);
尝试使用 C# .NET 5 网络应用程序执行 select 和 Oracle.ManagedDataAcces.Client (ODP.NET)。
Oracle.ManagedDataAcces.Client 版本是截至 02/06/2021 的最新版本 3.21.1。
错误:
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware1 An unhandled exception has occurred while executing the request. Oracle.ManagedDataAccess.Client.OracleException (0x80004005): ORA-01841: (full) year must be between -4713 and +9999, and not be 0 at OracleInternal.ServiceObjects.OracleConnectionImpl.VerifyExecution(Int32& cursorId, Boolean bThrowArrayBindRelatedErrors, SqlStatementType sqlStatementType, Int32 arrayBindCount, OracleException& exceptionForArrayBindDML, Boolean& hasMoreRowsInDB, Boolean bFirstIterationDone)
这是查询码
public async Task<int> GetMyCount(string userName, int THE_YEAR)
{
try
{
string TEST = "STACK_OVERFLOW_TEST";
builder.Clear();
builder.Append($@" SELECT COUNT(*)
FROM {configuration.SCHEMA}.SOME_TABLE CA
INNER JOIN {configuration.SCHEMA}.SOME_OTHER_TABLE CS
ON CS.ID=CA.ID ");
if (viewNotAll)
{
builder.Append($" INNER JOIN {unitOfWork.oracleDbOptions.DBSchemaQP}.ANOTHER_TABLE UT ON CA.SOME_FIELD = UT.SOME_FIELD ");
}
builder.Append(@$" WHERE CA.DATE_TO_FILET BETWEEN TO_DATE(CONCAT('0101', :THE_YEAR),'DDMMYYYY')
AND TO_DATE(CONCAT('3112', :THE_YEAR),'DDMMYYYY') ");
if (TEST == "NO")
builder.Append(" AND CS.TEST_FIELD=0 ");
else
builder.Append(" AND CS.TEST_FIELD=:THE_TEST_FIELD ");
int result = 0;
using (var cmd = unitOfWork.connection.CreateCommand())
{
cmd.Parameters.Add("THE_YEAR", OracleDbType.Int16, 4, THE_YEAR, ParameterDirection.Input);
cmd.Parameters.Add("THE_TEST_FIELD", OracleDbType.Varchar2, 20, userName, ParameterDirection.Input);
cmd.CommandText = builder.ToString();
using (var reader = await cmd.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
result = reader.IsDBNull(0) ? 0 : reader.GetInt32(0);
}
}
return result;
}
}
catch (Exception)
{
throw;
}
}
在 Oracle SQL Developer 或 PL/SQL 中执行查询有效。同样来自 visual studio 服务器 exporer 作品。弹出一个 window 询问参数,类型为 VARCHAR2,它可以很好地执行查询。
我什么都试过了。从 Int16、Int32、VARCHAR2 更改类型以用于测试目的,也基于 Oracle .NET type guide,它指出 Int16 用于长度为 4 的数字,在我的例子中是年份。 没有。
我还尝试使用显示的内容 in this Whosebug question 来检索 SQL 查询历史记录,显然,从外部触发的查询不会被记录。我无法通过此查询找到它们。
唯一有效的方法是直接连接查询中的值:
builder.Append(@$" WHERE CA.SOME_DATE BETWEEN TO_DATE(CONCAT('0101', '{THE_YEAR}'),'DDMMYYYY')
AND TO_DATE(CONCAT('3112', '{THE_YEAR}'),'DDMMYYYY') ");
但是我想使用参数来避免SQL注入。
我做错了什么?
更好用
builder.Append(@$" WHERE CA.DATE_TO_FILET BETWEEN :aDate AND :bDate");
cmd.Parameters.Add("aDate", OracleDbType.Date, ParameterDirection.Input).Value = new DateTime(THE_YEAR, 1, 1);
cmd.Parameters.Add("bDate", OracleDbType.Date, ParameterDirection.Input).Value = new DateTime(THE_YEAR, 12, 31);
CONCAT 连接两个字符串,因此 THE_YEAR 应该是四个字符的字符串而不是整数。你试过了吗
cmd.Parameters.Add("THE_YEAR", OracleDbType.Varchar2, 4, THE_YEAR.ToString(), ParameterDirection.Input);