NHibernate Oracle XMLType 问题
Posted
技术标签:
【中文标题】NHibernate Oracle XMLType 问题【英文标题】:NHibernate Oracle XMLType issue 【发布时间】:2012-04-19 06:54:41 【问题描述】:我们在 oracle 10g 数据库中有一个函数,它返回一个 XMLTYPE 值。我们正在尝试使用命令对象中的 ParameterDirection.ReturnValue 从函数中获取返回值。
但是我们遇到了错误
System.Data.OracleClient.OracleException (0x80131938):ORA-06550:第 1 行,第 27 列: PLS-00382:表达式类型错误 ORA-06550:第 1 行,第 7 列: PL/SQL:语句被忽略
如何解决?
【问题讨论】:
【参考方案1】:自从我从事这个工作以来已经有一段时间了,目前我没有一个工作项目来验证这个问题,但是,我相信这会解决你的问题。
我解决这个问题的方法是自定义构建 nHibernate 项目。我用下面的编辑编辑了 OracleDataClientDriver.cs 文件。您应该注意,我刚刚下载了该文件的当前版本,并且在我进行修复后的过去 2 年中它略有变化。如果您从 nHibernate 存储库获取文件的当前版本,并使用我要粘贴的代码对文件进行区分,您将看到更改。我的更改位于第 26、45、82-85 行(根据我的编辑)。
修复的主题是我必须添加一个从 nHibernate 映射文件类型到 XML 的 Oracle 数据类型的映射。 Oracle 驱动程序将处理这种类型,但缺少在 nHibernate 中使用它的逻辑。以下是解决此问题的方法。
开始粘贴-----
using System.Data;
using System.Reflection;
using NHibernate.AdoNet;
using NHibernate.Engine.Query;
using NHibernate.SqlTypes;
using NHibernate.Util;
namespace NHibernate.Driver
/// <summary>
/// A NHibernate Driver for using the Oracle.DataAccess DataProvider
/// </summary>
/// <remarks>
/// Code was contributed by <a href="http://sourceforge.net/users/jemcalgary/">James Mills</a>
/// on the NHibernate forums in this
/// <a href="http://sourceforge.net/forum/message.php?msg_id=2952662">post</a>.
/// </remarks>
public class OracleDataClientDriver : ReflectionBasedDriver, IEmbeddedBatcherFactoryProvider
private const string driverAssemblyName = "Oracle.DataAccess";
private const string connectionTypeName = "Oracle.DataAccess.Client.OracleConnection";
private const string commandTypeName = "Oracle.DataAccess.Client.OracleCommand";
private static readonly SqlType GuidSqlType = new SqlType(DbType.Binary, 16);
private readonly PropertyInfo oracleDbType;
private readonly object oracleDbTypeRefCursor;
private readonly object oracleDbTypeXmlType;
/// <summary>
/// Initializes a new instance of <see cref="OracleDataClientDriver"/>.
/// </summary>
/// <exception cref="HibernateException">
/// Thrown when the <c>Oracle.DataAccess</c> assembly can not be loaded.
/// </exception>
public OracleDataClientDriver()
: base(
driverAssemblyName,
connectionTypeName,
commandTypeName)
System.Type parameterType = ReflectHelper.TypeFromAssembly("Oracle.DataAccess.Client.OracleParameter", driverAssemblyName, false);
oracleDbType = parameterType.GetProperty("OracleDbType");
System.Type oracleDbTypeEnum = ReflectHelper.TypeFromAssembly("Oracle.DataAccess.Client.OracleDbType", driverAssemblyName, false);
oracleDbTypeRefCursor = System.Enum.Parse(oracleDbTypeEnum, "RefCursor");
oracleDbTypeXmlType = System.Enum.Parse(oracleDbTypeEnum, "XmlType");
/// <summary></summary>
public override bool UseNamedPrefixInSql
get return true;
/// <summary></summary>
public override bool UseNamedPrefixInParameter
get return true;
/// <summary></summary>
public override string NamedPrefix
get return ":";
/// <remarks>
/// This adds logic to ensure that a DbType.Boolean parameter is not created since
/// ODP.NET doesn't support it.
/// </remarks>
protected override void InitializeParameter(IDbDataParameter dbParam, string name, SqlType sqlType)
// if the parameter coming in contains a boolean then we need to convert it
// to another type since ODP.NET doesn't support DbType.Boolean
switch (sqlType.DbType)
case DbType.Boolean:
base.InitializeParameter(dbParam, name, SqlTypeFactory.Int16);
break;
case DbType.Guid:
base.InitializeParameter(dbParam, name, GuidSqlType);
break;
case DbType.Xml:
dbParam.ParameterName = base.FormatNameForParameter(name);
oracleDbType.SetValue(dbParam, oracleDbTypeXmlType, null);
break;
default:
base.InitializeParameter(dbParam, name, sqlType);
break;
protected override void OnBeforePrepare(IDbCommand command)
base.OnBeforePrepare(command);
CallableParser.Detail detail = CallableParser.Parse(command.CommandText);
if (!detail.IsCallable)
return;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = detail.FunctionName;
IDbDataParameter outCursor = command.CreateParameter();
oracleDbType.SetValue(outCursor, oracleDbTypeRefCursor, null);
outCursor.Direction = detail.HasReturn ? ParameterDirection.ReturnValue : ParameterDirection.Output;
command.Parameters.Insert(0, outCursor);
#region IEmbeddedBatcherFactoryProvider Members
System.Type IEmbeddedBatcherFactoryProvider.BatcherFactoryClass
get return typeof (OracleDataClientBatchingBatcherFactory);
#endregion
结束粘贴-------
【讨论】:
以上是关于NHibernate Oracle XMLType 问题的主要内容,如果未能解决你的问题,请参考以下文章
oracle, xmltype/clob substr 循环
将 oracle xmltype 表字段选择到 xmltype 变量中会导致空对象
Oracle XMLTable / XMLTYPE(不知道)