C# NHibernate-针对XmlType的Oracle 11g配置

C# NHibernate-针对XmlType的Oracle 11g配置,c#,nhibernate,configuration,xmltype,C#,Nhibernate,Configuration,Xmltype,我试图让NHibernate使用Oracle 11g的XmlType 将引发以下异常: Dialect does not support DbType.Xml 我的配置如下所示: <?xml version="1.0" encoding="utf-8" ?> <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2"> <session-factory> <proper

我试图让NHibernate使用Oracle 11g的XmlType

将引发以下异常:

Dialect does not support DbType.Xml
我的配置如下所示:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>
    <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
    <property name="dialect">NHibernate.Dialect.Oracle10gDialect</property>
    <property name="connection.driver_class">NHibernate.Driver.OracleClientDriver</property>
    <property name="connection.connection_string">...</property>
    <property name="show_sql">false</property>
  </session-factory>
</hibernate-configuration>
映射文件的重要部分:

    <property name="History" />

尝试使用自定义Oracle数据客户端驱动程序,以下是代码:

using System;
using System.Data;
using System.Data.Common;
using System.Reflection;
using NHibernate;
using NHibernate.AdoNet;
using NHibernate.Driver;
using NHibernate.Engine.Query;
using NHibernate.SqlTypes;
using NHibernate.Util;
using Oracle.DataAccess.Client;

/// <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 CustomOracleDataClientDriver : 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 CustomOracleDataClientDriver()
        : base(
            DriverAssemblyName,
            ConnectionTypeName,
            CommandTypeName) {
        var parameterType = ReflectHelper.TypeFromAssembly("Oracle.DataAccess.Client.OracleParameter",
            DriverAssemblyName, false);
        this.oracleDbType = parameterType.GetProperty("OracleDbType");

        var oracleDbTypeEnum = ReflectHelper.TypeFromAssembly("Oracle.DataAccess.Client.OracleDbType",
            DriverAssemblyName, false);
        this.oracleDbTypeRefCursor = Enum.Parse(oracleDbTypeEnum, "RefCursor");
        this.oracleDbTypeXmlType = 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 ":"; }
    }

    #region IEmbeddedBatcherFactoryProvider Members

    Type IEmbeddedBatcherFactoryProvider.BatcherFactoryClass {
        get { return typeof (OracleDataClientBatchingBatcherFactory); }
    }

    #endregion

    /// <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 = this.FormatNameForParameter(name);
                this.oracleDbType.SetValue(dbParam, this.oracleDbTypeXmlType, null);
                break;
            default:
                base.InitializeParameter(dbParam, name, sqlType);
                break;
        }
    }

    protected override void OnBeforePrepare(IDbCommand command) {
        base.OnBeforePrepare(command);

        ((OracleCommand) command).BindByName = true;

        var detail = CallableParser.Parse(command.CommandText);

        if (!detail.IsCallable)
            return;

        command.CommandType = CommandType.StoredProcedure;
        command.CommandText = detail.FunctionName;

        var outCursor = command.CreateParameter();
        this.oracleDbType.SetValue(outCursor, this.oracleDbTypeRefCursor, null);

        outCursor.Direction = detail.HasReturn ? ParameterDirection.ReturnValue : ParameterDirection.Output;

        command.Parameters.Insert(0, outCursor);
    }
}
使用系统;
使用系统数据;
使用System.Data.Common;
运用系统反思;
使用NHibernate;
使用NHibernate.AdoNet;
使用NHibernate.Driver;
使用NHibernate.Engine.Query;
使用NHibernate.SqlTypes;
使用NHibernate.Util;
使用Oracle.DataAccess.Client;
/// 
///用于使用Oracle.DataAccess数据提供程序的NHibernate驱动程序
/// 
/// 
///代码是由在NHibernate论坛上发表的。
/// 
公共类CustomOracleDataClientDriver:ReflectionBasedDriver,IEmbeddedBatcherFactoryProvider{
private const string driversassemblyname=“Oracle.DataAccess”;
private const string ConnectionTypeName=“Oracle.DataAccess.Client.OracleConnection”;
private const string CommandTypeName=“Oracle.DataAccess.Client.OracleCommand”;
私有静态只读SqlType GuidSqlType=newsqltype(DbType.Binary,16);
私有只读属性信息oracleDbType;
私有只读对象oracleDbTypeRefCursor;
私有只读对象oracleDbTypeXmlType;
/// 
///初始化的新实例。
/// 
///当
///Oracle.DataAccess
///无法加载程序集。
公共CustomOracleDataClientDriver()
:基本(
DriverRassemblyName,
ConnectionTypeName,
命令类型(名称){
var parameterType=ReflectHelper.TypeFromAssembly(“Oracle.DataAccess.Client.OracleParameter”,
DriverAssemblyName,false);
this.oracleDbType=parameterType.GetProperty(“oracleDbType”);
var oracleDbTypeEnum=ReflectHelper.TypeFromAssembly(“Oracle.DataAccess.Client.OracleDbType”,
DriverAssemblyName,false);
this.oracleDbTypeRefCursor=Enum.Parse(oracleDbTypeEnum,“RefCursor”);
this.oracledbypexmltype=Enum.Parse(oracledbypeenum,“XmlType”);
}
/// 
/// 
公共重写bool UseNamedPrefixInSql{
获取{return true;}
}
/// 
/// 
公共覆盖布尔UseNamedPrefixin参数{
获取{return true;}
}
/// 
/// 
公共重写字符串NamedPrefix{
获取{return”:“;}
}
#区域IEMBedBatcherFactoryProvider成员
类型IEMBededBatcherFactoryProvider.BatcherFactoryClass{
获取{返回类型(OracleDataClientBatchingBatcherFactory);}
}
#端区
/// 
///这将添加逻辑以确保不会创建DbType.Boolean参数,因为ODP.NET不支持它。
/// 
受保护的重写void InitializeParameter(IDbDataParameter dbParam,字符串名称,SqlType SqlType){
//如果传入的参数包含布尔值,则需要对其进行转换
//由于ODP.NET不支持DbType.Boolean,因此无法转换为其他类型
开关(sqlType.DbType){
case DbType.Boolean:
InitializeParameter(dbParam,name,SqlTypeFactory.Int16);
打破
案例DbType.Guid:
InitializeParameter(dbParam、name、GuidSqlType);
打破
case DbType.Xml:
dbParam.ParameterName=此.FormatNameForParameter(名称);
this.oracleDbType.SetValue(dbParam,this.oracleDbTypeXmlType,null);
打破
违约:
InitializeParameter(dbParam,name,sqlType);
打破
}
}
受保护的覆盖无效OnBeforePrepare(IDbCommand){
base.onbefore准备(命令);
((OracleCommand)命令).BindByName=true;
var detail=CallableParser.Parse(command.CommandText);
如果(!detail.IsCallable)
返回;
command.CommandType=CommandType.storedProcess;
command.CommandText=detail.FunctionName;
var outCursor=command.CreateParameter();
this.oracleDbType.SetValue(outCursor,this.oracleDbTypeRefCursor,null);
outCursor.Direction=detail.HasReturn?ParameterDirection.ReturnValue:ParameterDirection.Output;
command.Parameters.Insert(0,outCursor);
}
}
NHibernate配置:

...
<property name="connection.driver_class">
  Your.NameSpace.CustomOracleDataClientDriver, Your.Assembly.Name
</property>
<property name="dialect">
  NHibernate.Dialect.Oracle10gDialect
</property>
...
。。。
Your.NameSpace.CustomOracleDataClientDriver,Your.Assembly.Name
NHibernate.方言
...

下面是一个示例

,在该示例中,我可以找到ExecuteType或IDbProfiler类吗?@Daffi,您的XmlType属性映射是什么?您可以尝试在映射中指定sql类型(参见要点),我刚刚测试过,它对我有效(.NET 4.0,Oracle.DataAccess v4.112.3.0),这是完整的源代码,我和你一样做了sam,现在我得到了一个例外:未知标识符。我想这是因为我的Oracle.DataAccess版本是:2.112.1.0。。。但我还是希望.NET4.0的版本…它终于成功了。我仍在使用旧的DataAccess版本,我的问题是名称错误的列(日期=保留!)
...
<property name="connection.driver_class">
  Your.NameSpace.CustomOracleDataClientDriver, Your.Assembly.Name
</property>
<property name="dialect">
  NHibernate.Dialect.Oracle10gDialect
</property>
...