2012-04-19 61 views
1

我們在oracle 10g數據庫中有一個函數,它返回一個XMLTYPE值。我們試圖從命令對象中使用ParameterDirection.ReturnValue獲取函數的返回值。NHibernate Oracle XMLType問題

但我們得到誤差作爲

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 for XML的映射。 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 
    } 

糊底-------