문제

Windows 7에서 Nhibernate로 작업하는 Informix를 얻으려고 노력하고 있습니다. 지금 Informix와 잘 작동하는 연결 문자열이 있습니다.

Database = db; server = server : port; uid = username; password = password; pooling = false

IBM.Data.informix .NET 제공 업체 버전 9.0.0.2를 사용하고 있습니다.

우리는 실행중인 Informix 서버와 함께이 공급자를 사용하여 잘 작동하는 여러 가지 응용 프로그램이 있습니다.

내 nhibernate 응용 프로그램은 지금 Informix 서버에 연결하고 있지만 문제는 생성하는 SQL의 형태입니다.

내 nhibernate 코드가 이렇게 보이면

using (ISession session = Config.SessionFactory.OpenSession())
{
    return session
        .CreateCriteria<DBTable>()
        .Add(Restrictions.Eq("FieldValue", true))
        .List<DBTable>();
}

나는 Informix를 처음 접했지만 내가 틀리지 않으면 올바른 SQL이 될 것입니다.

fieldValue = 't'에서 dbtable에서 *를 선택하십시오.

그러나 대신 SQL은 생산되고 있습니다.

fieldValue = true에서 dbtable에서 *를 선택하십시오

작동하지 않습니다. Nhibernate 구성 파일에 이와 같은 물건을 추가하려고했습니다.

<property name="query.substitutions">True=T,False=F</property>
<property name="query.substitutions">True 'T',False 'F'</property>
<property name="query.substitutions">True='T',False='F'</property>
<property name="query.substitutions">True T,False F</property>

그러나 그것은 단지 작동하지 않는 것 같습니다. query.substitutions를 사용하는 방법에 대한 일관된 설명서를 찾을 수 없었으며 사용중인 데이터베이스 유형에 따라 다른 것처럼 보였습니다.

도움이 되었습니까?

해결책

어떤 버전의 nhibernate를 사용하고 있습니까?

FieldValue의 속성 유형은 무엇입니까?

나는 Informix와 함께 nhibernate를 사용하고 있으며 부울 제한과 함께 쿼리가 잘 작동합니다. 이들은 관련 구성 값입니다.

<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.driver_class">NHibernate.Driver.IfxDriver</property>
<property name="dialect">NHibernate.Dialect.InformixDialect1000</property>

다른 팁

원본 버전의 질문에 대한 논평

이에 답하기 위해서는 더 많은 정보가 필요하며 의견에 맞는 것보다 더 많은 정보 요청이 필요합니다.

먼저, 나는 당신이 Windows의 일부 변형 (그러나 어느 것입니까?)에서 IBM Informix Dynamic Server (IDS)를 사용하고 있다고 토론에서 가정합니다. 어떤 버전의 ID를 사용하고 있습니까? 또한 어떤 버전의 ClientSDK를 사용하고 있습니까?

다음으로 일부 프로그램을 사용하여 IDS 데이터베이스에 연결할 수 있다고 가정합니다. 문제는 액세스가 아닌 NHibernate를 통한 액세스와 관련이 있습니다. 문제가 아직 ID에 전혀 액세스 할 수 없다는 것이면 디버깅 단계는 '대체 액세스 방법을 통한 것이 아니라'와 다소 다릅니다.

다른 방법을 통해 연결할 때 (a) 다른 방법은 무엇이며 (b) 사용하는 연결 문자열은 무엇입니까? 문자열 값의 '구조적 세부 사항'을보고 싶습니다. 예를 들어, 데이터베이스를 'instive@secret'로 지정하면 'xxxxxxxxx@yyyyyy'표기법을보고 싶습니다. 비록 이름이 민감하고 비밀임을 알 필요는 없기 때문에 우리는 필요합니다. 이름이 어떻게 생겼는지 알 수 있습니다. 문자열의 다른 값에 대해서도 마찬가지입니다. 당신은 당신이 민감한 정보를 제거했다고 말했지만, 당신은 당신이 제공 한 내용이 합리적인지 알 수 없을 정도로 철저히 해냈습니다.

SetNet32를 사용하여 Informix 환경 값을 설정 했습니까? Windows 플랫폼에만 적용되는 질문입니다 (Unix는 중앙 레지스트리가 아닌 일반 환경 변수를 사용합니다). 그렇다면 무엇을 설정 했습니까?

비 원자경 패키지의 작동 연결 문자열은 NHibernate의 비 작업 문자열과 어떻게 비교됩니까?

마지막으로 (현재) IBM DB2 .NET 드라이버와 Informix OLEDB 드라이버를 모두 사용하려고했음을 보여주었습니다. DB2 .NET 드라이버는 DRDA 프로토콜을 사용하여 ID와 대화하는 반면 Informix 드라이버는 SQLI 프로토콜을 사용합니다. 기본적으로 IDS는 SQLI 연결에 대해서만 장려합니다. DRDA 연결을 수락하려면 ID를 구성해야합니다. IDS 관리의 세부 사항 중 일부에 들어가는 수정 - 우리가 처리 할 필요가 없지만 우리는 할 수 있기를 바랍니다.

정보를 얻는 방법은 무엇입니까? 다른 사람들이 문제를 쉽게 볼 수 있도록 질문에 추가 정보를 추가하여 질문을 편집하는 것이 좋습니다. (저는 Windows에서 ID를 가진 전문가가 아닙니다. 뒷마당은 Unix 기반입니다. 다른 사람들이 답을 제공하도록 도와야하지만 필요한 정보는 아직 사용할 수 없습니다.)

수정 된 질문에 대한 논평

IDS는 정통적인 방식으로 부울 유형을 지원합니다. true 또는 false (또는 unknown) 부울 값으로; 사용합니다 't' 그리고 'f' 대신에. 결과적으로, nhibernate에 의해 생성 된 코드는 ID에 유효하지 않습니다 (나는 그 효과에 대한 인수를 받아들입니다). 문제를 해결하는 좋은 방법이 있는지 확실하지 않습니다. Nhibernate가 진실과 거짓 대신 인용 된 캐릭터를 전달하도록 설득 할 수 있다면, 당신은 싸우는 기회를 가지고 있습니다.

이 때문에 : FieldValue = 't'나는 FieldValue에 부울이 아닌 데이터베이스에 입력 된 경우 (1) char (1)가 있다는 결론을 내립니다. 그렇다면 사용해야합니다.

Restrictions.Eq("FieldValue", "T")

나는 이것을 테스트하지 않았지만 당신의 문제는 정보가 아니라고 생각합니다. 다른 데이터베이스에서 동일한 오류가 발생합니다.

이것은 모든 nhibernate 방언이 TobooleanValuestring 방법을 제공하기 때문입니다. 기본적으로 부울 값은 "0"및 "1"(다른 데이터베이스에서 "t"를 기대할 수 없음)에 매핑되며 Informix의 경우 "t"및 "f"에 매핑됩니다. 분명히이 방법은 제한에 의해 사용되지 않는다.

EQ는 내부 부울 변수를 사용하고 (인수가 부울이기 때문에) 데이터베이스 열이 문자 유형이기 때문에 "Tostring"메소드를 호출하고 있습니다. 진정한 가치에 대한 "Tostring"의 결과는 단지 "true"입니다.

새로운 Informix 드라이버가 다른 연결을 사용하고 있으며 부울을 오해하고 있기 때문에 문제가 발생합니다.

내가 찾은 솔루션은 nhibernate.driver.ifxdriver에서 상속 된 새로운 nhibernate 드라이버를 만드는 것입니다. 쿼리 실행 직전에 매개 변수를 처리합니다.

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NHibernate;
using NHibernate.Driver;
using NHibernate.SqlCommand;
using NHibernate.SqlTypes;

namespace DataAccess
{
    public class NHibernateCustomDriver : NHibernate.Driver.IfxDriver
    {
        public override IDbCommand GenerateCommand(CommandType type, SqlString sqlString, SqlType[] parameterTypes)
        {
            IDbCommand cmd = CreateCommand();
            cmd.CommandType = type;

            SetCommandTimeout(cmd);
            SetCommandText(cmd, sqlString, parameterTypes);
            SetCommandParameters(cmd, parameterTypes);
            return cmd;
        }

        private void SetCommandText(IDbCommand cmd, SqlString sqlString, SqlType[] parameterTypes)
        {
            SqlStringFormatter formatter = GetSqlStringFormatter();
            formatter.Format(sqlString);

            int index = 0;
            int count = 0;
            string newCommand = formatter.GetFormattedText();
            index = newCommand.IndexOf("?");
            while (index >= 0)
            {
                if (parameterTypes[count].DbType == DbType.Boolean)
                {
                    newCommand = newCommand.Substring(0, index) + "CAST(?  AS BOOLEAN)" + newCommand.Substring(index + 1);
                    index = newCommand.IndexOf("?", index + 1);
                }
                count++;
                index = newCommand.IndexOf("?", index + 1);

            }

            cmd.CommandText = newCommand;

        }

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

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

nhibernate 구성은 새 클래스로 설정해야합니다.

cfg.SetProperty("connection.driver_class", "DataAccess.NHibernateCustomDriver, DataAccess");

또한 부울을 처리하려면 사용자 정의 유형을 만들어야합니다.

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NHibernate.Type;

namespace DataAccess
{
    public class NHibernateUnixBooleanType : BooleanType
    {
        public override void Set(IDbCommand cmd, object value, int index)
        {
            cmd.Parameters[index] = CloneParameter(cmd, cmd.Parameters[index] as IDbDataParameter, value as bool?);
        }
        private IDbDataParameter CloneParameter(IDbCommand cmd, IDbDataParameter originalParameter, bool? value)
        {
            var clone = cmd.CreateParameter();
            clone.DbType = DbType.String;
            clone.Value = value.Value ? "t" : "f";
            clone.ParameterName = originalParameter.ParameterName;
            return clone;
        }
    }
}

매핑 파일 에서이 유형을 설정합니다.

<property name="Property" column="column" type="DataAccess.NHibernateUnixBooleanType, DataAccess"></property>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top