2012-04-19 2 views
1

У нас есть одна функция в базе данных оракула 10g, которая возвращает значение XMLTYPE. мы пытаемся получить возвращаемое значение из функции с помощью параметра ParameterDirection.ReturnValue в объекте команды.NHibernate Oracle XMLType issue

но мы получаем ошибку в

System.Data.OracleClient.OracleException (0x80131938): ORA-06550: Строка 1, столбец 27: PLS-00382: выражение неправильного типа ORA-06550: строка 1, столбец 7: PL/SQL: заявление игнорируется

Как это решить?

ответ

0

Это было немного с тех пор, как я работал над этим, и в настоящее время у меня нет рабочего проекта для проверки проблемы, однако я верю, что это решит вашу проблему.

Как я решил, это было сделать пользовательскую сборку проекта nHibernate. Я редактировал файл OracleDataClientDriver.cs с изменениями ниже. Вы должны отметить, что я только что загрузил текущую версию этого файла, и он изменился за последние 2 года с момента моего исправления. Если вы выберете текущую версию файла из репозитория nHibernate и запишите файл с кодом, который я собираюсь вставить, вы увидите изменения. Мои изменения указаны в строках (согласно моему редактору) 26, 45, 82-85.

Тема исправления заключается в том, что мне пришлось добавить сопоставление типов файлов сопоставления nHibernate в Oracle Data Type для XML. Драйвер Oracle будет обрабатывать этот тип, но логика его использования в nHibernate отсутствует. Ниже приведено исправление.

Start Paste -----

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 
    } 

End Paste -------

Смежные вопросы