2

私はレガシーSQLBaseデータベースに取り組んでおり、NHibernateを使用して新しいプロジェクトをセットアップしようとしています。

大きな問題は、SQLBaseがSQLのバインド変数を期待する形式です。形式は明示的にする必要があります

INSERT INTO ... VALUES (:1,:2,:3); 
SELECT ... FROM TABLE WHERE ID=:1 AND NAME=:2;

現在、NHibernateはバインド変数に「:p0、:p1、...」形式を使用しており、SQLBaseで「無効なプログラムバインド変数」SQL例外が発生します。

問題は、数値の前の「p」であり、パラメーターが0から始まることです。SQLBaseには1から始まるパラメーターが必要です。

バインド変数の「p」を削除し、0ではなく1で開始するようにNHibernateを構成/変更する方法はありますか?クラスマッピングのsql-insert、sql-update、およびsql-deleteマッピングを使用して、INSERT、UPDATE、およびDELETEのパラメーターの形式を変更できましたが、SELECTパラメーターを変更する唯一の方法は、マッピングへの名前付きクエリ。

明らかに、これは好ましい方法ではありません。バインド変数の生成方法を変更するためのより良い方法はありますか?私はすでに独自のドライバー(OleDbDriverから継承)とDialect(GenericDialectから)を作成し、SQLBaseが最初に機能するようにいくつかの変更を加えました。

設定もしてみました

private static string ToParameterName(int index)
{
  return "p" + index;
}

String.Emptyを返しますが、役に立ちません。しかし、それでパラメータから「p」プレフィックスが削除されたとしても、1ではなく0から始まるという問題があります。

この動作またはNHibernateを変更する機会はありますか?

編集:私は今、他のいくつかのパラメータ関数も変更しようとしました:

string ISqlParameterFormatter.GetParameterName(int index)
        {
            int ret = index + 1;
            return (NamedPrefix + ret);
        }

        private void SetCommandParameters(IDbCommand cmd, SqlType[] sqlTypes)
        {
            for (int i = 0; i < sqlTypes.Length; i++)
            {
                int ret = i + 1;
                string paramName = ret.ToString();
                IDbDataParameter dbParam = GenerateParameter(cmd, paramName, sqlTypes[i]);
                cmd.Parameters.Add(dbParam);
            }
        }

        protected override void InitializeParameter(IDbDataParameter dbParam, string name, SqlType sqlType)
        {
            if (sqlType == null)
            {
                throw new QueryException(String.Format("No type assigned to parameter '{0}'", name));
            }
            name = name.Remove(0, 1);
            dbParam.ParameterName = (Int32.Parse(name) + 1).ToString();
            dbParam.DbType = sqlType.DbType;
        }

これらの変更により、SQLパラメーターは ":1、:2"などになりますが、バインディングも壊れました。パラメーターはクエリにまったく追加されなくなりました:(

Edit2:完全なドライバーと方言コードは次のとおりです。

namespace NHSQLBase
{
    public class SQLBaseDriver : OleDbDriver, ISqlParameterFormatter
    {
        public override bool UseNamedPrefixInSql
        {
            get
            {
                return true;
            }
        }

        public override bool UseNamedPrefixInParameter
        {
            get
            {
                return false;
            }
        }

        public override string NamedPrefix
        {
            get
            {
                return ":";
            }
        }

        private static string ToParameterName(int index)
        {
            return (index + 1).ToString();
        }


        string ISqlParameterFormatter.GetParameterName(int index)
        {
            int ret = index + 1;
            return (NamedPrefix + ret);
        }

        private void SetCommandParameters(IDbCommand cmd, SqlType[] sqlTypes)
        {
            for (int i = 0; i < sqlTypes.Length; i++)
            {
                int ret = i + 1;
                string paramName = ret.ToString();
                IDbDataParameter dbParam = GenerateParameter(cmd, paramName, sqlTypes[i]);
                cmd.Parameters.Add(dbParam);
            }
        }

        protected override void InitializeParameter(IDbDataParameter dbParam, string name, SqlType sqlType)
        {
            if (sqlType == null)
            {
                throw new QueryException(String.Format("No type assigned to parameter '{0}'", name));
            }
            name = name.Remove(0, 1);
            dbParam.ParameterName = (Int32.Parse(name) + 1).ToString();
            dbParam.DbType = sqlType.DbType;
        }
    }

    public class SQLBaseDialect : GenericDialect
    {
        public override string ForUpdateString
        {
            get
            {
                return " ";
            }
        }

        public override bool ForUpdateOfColumns
        {
            get
            {
                return true;
            }
        }

        public override string GetForUpdateString(string aliases)
        {
            return " for update of " + aliases;
        }

        public override bool SupportsOuterJoinForUpdate
        {
            get
            {
                return false;
            }
        }

        public override bool SupportsParametersInInsertSelect
        {
            get
            {
                return false;
            }
        }
    }
}
4

1 に答える 1

1

少し試行錯誤した後、私はあなたの問題の根本を見つけたと思います。SQLBaseDriver主な問題は、からの継承が原因のようOleDbDriverです。これがに変更されReflectionBasedDriver、コンストラクターが正しく設定されると、問題なく挿入を実行できました。

ドライバーと方言の両方の動作バージョンについては、以下を参照してください。

注意すべき点の1つは、SQLBaseの.NetデータプロバイダーdllであるGupta.SQLBase.Data.dllが、これが機能するためにNHibernate.dllと同じフォルダーにある必要があることです。

public class SQLBaseDriver : NHibernate.Driver.ReflectionBasedDriver
{
    public SQLBaseDriver()
        : base("Gupta.SQLBase.Data",
               "Gupta.SQLBase.Data.SQLBaseConnection",
               "Gupta.SQLBase.Data.SQLBaseCommand")
    {

    }
    public override bool UseNamedPrefixInSql
    {
        get { return true; }
    }

    public override bool UseNamedPrefixInParameter
    {
        get { return false; }
    }

    public override string NamedPrefix
    {
        get { return ":"; }
    }
}

方言コード:

public class SQLBaseDialect : GenericDialect
{
    public override string ForUpdateString
    {
        get { return " "; }
    }

    public override bool ForUpdateOfColumns
    {
        get { return true; }
    }

    public override string GetForUpdateString(string aliases)
    {
        return " for update of " + aliases;
    }

    public override bool SupportsOuterJoinForUpdate
    {
        get { return false; }
    }

    public override bool SupportsParametersInInsertSelect
    {
        get { return false; }
    }
}
于 2013-03-23T15:15:22.703 に答える