我正在尝试将加密的 unicode 文本存储在 OracleRAW
字段中。AL32UTF8
在加密之前,为了提高效率,我将字符串转换为原始字节数组。(NLS_NCHAR_CHARACTERSET
是AL16UTF16
)。
从UTL_I18N 包中抛出LOSSY_CHARACTERSET_CONVERSION
( ORA-12713
) 异常。
我故意设置NCharConversionException = true
让它抛出异常,而不是让有损转换“希腊化”输出。
我究竟做错了什么?
为了方便起见,这里是一个使用 Dapper 的示例。没有调用 string_to_raw 的 NVarchar2 参数绑定可以正常工作。
/// <summary>
/// using Dapper;
/// using Oracle.ManagedDataAccess.Client
///
/// </summary>
[Test, Explicit]
public void Dapper_Sql_NLS_StringToRaw_ReturnValue_RefCursor_SmokeTest()
{
var parms = new OracleDynamicParameters();
var cn = ApiThreadContext.Current.Connection.DbConnection as OracleConnection;
OracleGlobalization og = cn.GetSessionInfo();
og.NCharConversionException = true; //throws LOSSY_CHARACTERSET_CONVERSION
cn.SetSessionInfo(og);
var expected = "Шон";
parms.Add(":in_plain", expected, OracleDbType.NVarchar2, ParameterDirection.Input);
parms.Add(":rc", dbType: OracleDbType.RefCursor, direction: ParameterDirection.ReturnValue);
//'Шон'
var result = cn.Query<dynamic>(
"select utl_i18n.string_to_raw(:in_plain, 'AL32UTF8') from dual",
//"select :in_plain from dual",
parms,
commandType: CommandType.Text
);
}
客户端
Windows 7 Professional x64 SP1 .Net 4.6 Full
Oracle.ManagedDataAccess.dll
4.12.1.2400(最新)。
Oracle全球化设置:
{Oracle.ManagedDataAccess.Client.OracleGlobalization}
Calendar: "GREGORIAN"
Comparison: "BINARY"
Currency: "£"
DateFormat: "DD-MON-YYYY HH24:MI:SS"
DateLanguage: "ENGLISH"
DualCurrency: "€"
ISOCurrency: "UNITED KINGDOM"
Language: "ENGLISH"
LengthSemantics: "BYTE"
NCharConversionException: true
NumericCharacters: ".,"
Sort: "BINARY"
Territory: "UNITED KINGDOM"
TimeStampFormat: "DD-MON-RR HH24.MI.SSXFF"
TimeStampTZFormat: "DD-MON-RR HH24.MI.SSXFF TZR"
TimeZone: "Europe/London"
我没有NLS_LANG
在客户端上设置环境变量,因为上面应该涵盖。(无论如何,我都没有检查它是否对托管提供者有任何影响)。
服务器
NLS_DATABASE_PARAMETERS
NLS_NCHAR_CHARACTERSET AL16UTF16
NLS_LANGUAGE ENGLISH
NLS_TERRITORY UNITED KINGDOM
NLS_CURRENCY £
NLS_ISO_CURRENCY UNITED KINGDOM
NLS_NUMERIC_CHARACTERS .,
NLS_CHARACTERSET WE8MSWIN1252
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE ENGLISH
NLS_SORT BINARY
NLS_TIME_FORMAT HH24.MI.SSXFF
NLS_TIMESTAMP_FORMAT DD-MON-RR HH24.MI.SSXFF
NLS_TIME_TZ_FORMAT HH24.MI.SSXFF TZR
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH24.MI.SSXFF TZR
NLS_DUAL_CURRENCY €
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CONV_EXCP FALSE
NLS_RDBMS_VERSION 10.2.0.5.0
V$版本
Oracle Database 10g Release 10.2.0.5.0 - 64bit Production
PL/SQL Release 10.2.0.5.0 - Production
CORE 10.2.0.5.0 Production
TNS for 64-bit Windows: Version 10.2.0.5.0 - Production
NLSRTL Version 10.2.0.5.0 - Production
客户端错误堆栈:
Test 'UddFixture.Dapper_Sql_NLS_StringToRaw_SmokeTest' failed:
Oracle.ManagedDataAccess.Client.OracleException : ORA-12713: Character data loss in NCHAR/CHAR conversion
ORA-06512: at "SYS.UTL_I18N", line 321
ORA-06512: at line 1
at OracleInternal.ServiceObjects.OracleCommandImpl.VerifyExecution(OracleConnectionImpl connectionImpl, Int32& cursorId, Boolean bThrowArrayBindRelatedErrors, OracleException& exceptionForArrayBindDML, Boolean& hasMoreRowsInDB, Boolean bFirstIterationDone)
at OracleInternal.ServiceObjects.OracleCommandImpl.ExecuteReader(String commandText, OracleParameterCollection paramColl, CommandType commandType, OracleConnectionImpl connectionImpl, OracleDataReaderImpl& rdrImpl, Int32 longFetchSize, Int64 clientInitialLOBFS, OracleDependencyImpl orclDependencyImpl, Int64[] scnForExecution, Int64[]& scnFromExecution, OracleParameterCollection& bindByPositionParamColl, Boolean& bBindParamPresent, Int64& internalInitialLOBFS, OracleException& exceptionForArrayBindDML, Boolean isDescribeOnly, Boolean isFromEF)
at Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteReader(Boolean requery, Boolean fillRequest, CommandBehavior behavior)
at Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteDbDataReader(CommandBehavior behavior)
Core\Connectivity\Dapper\SqlMapper.cs(1631,0): at Dapper.SqlMapper.<QueryImpl>d__61`1.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
Core\Connectivity\Dapper\SqlMapper.cs(1506,0): at Dapper.SqlMapper.Query[T](IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Boolean buffered, Nullable`1 commandTimeout, Nullable`1 commandType)
UddFixture.cs(330,0): at UddFixture.Dapper_Sql_NLS_StringToRaw_SmokeTest()