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 开始的参数。

有什么方法可以配置/更改 NHibernate 以删除绑定变量中的“p”,并以 1 而不是 0 开头?我能够在我的类映射中使用 sql-insert、sql-update 和 sql-delete 映射更改 INSERT、UPDATE 和 DELETE 的参数格式,但我发现更改 SELECT 参数的唯一方法是编写大量命名查询到我的映射。

显然这不是首选方式。有没有更好的方法来改变绑定变量的生成方式?我已经制作了自己的驱动程序(继承自 OleDbDriver)和方言(继承自 GenericDialect)并更改了一些东西以使 SQLBase 能够正常工作。

我也试过设置

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

返回 String.Empty,但无济于事。但即使这会从参数中删除“p”前缀,我仍然会遇到它们从 0 而不是 1 开始的问题。

有没有机会改变这种行为或 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并且正确填充了构造函数,我就可以毫无问题地执行插入。

请参阅下面的驱动程序和方言的工作版本。

需要注意的一点是,用于 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 回答