NHibernate 3 GA LINQ с новой проблемой булевых преобразований Fluent NHbernate - PullRequest
2 голосов
/ 09 декабря 2010

Я использую бета-версии NHibernate с Fluent NHibernate. Все было хорошо, пока я не перешел на выпуск GA со всеми бинарными файлами из Fluent NHibernate http://fluentnhibernate.org/downloads

Проблема в том, что в базе данных Oracle есть столбцы char с буквой «Y» или «N» для логических значений «да / нет». У моей модели есть bools.

public class ApplicationUser 
{
    public virtual string UserId { get; set; }
    public virtual string RoleId { get; set; }        
    public virtual string Prefix { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string MiddleName { get; set; }
    public virtual string LastName { get; set; }
    public virtual string Suffix { get; set; }
    public virtual string Title { get; set; }
    public virtual string Company { get; set; }
    public virtual string UserName { get; set; }
    public virtual string RoleName { get; set; }
    public virtual string RoleGroup { get; set; }
    public virtual bool IsRoleActive { get; set; }
    public virtual bool IsUserActive { get; set; }

}

В моих отображениях Fluent NH я применил CustomType, чтобы выполнить преобразование. Все работало отлично.

public ApplicationUserMap()
{
    Schema("TEST");
    Table("V_APPLICATION_USER_ROLE");
    Id(x => x.UserId)
        .Column("USER_ID");
    Map(x => x.RoleId)
        .Column("ROLE_ID");
    Map(x => x.Prefix)               
        .Column("NAME_PRE");
    Map(x => x.FirstName)
        .Column("NAME_FIRST");
    Map(x => x.MiddleName)
        .Column("NAME_MI");
    Map(x => x.LastName)
        .Column("NAME_LAST");
    Map(x => x.Suffix)
        .Column("NAME_SUF");
    Map(x => x.Title)
        .Column("TITLE");
    Map(x => x.Company)
        .Column("COMPANY");
    Map(x => x.UserName)
        .Column("LOGIN_ID");
    Map(x => x.RoleName)
        .Column("ROLE_NAME");
    Map(x => x.RoleGroup)
        .Column("ROLE_GROUP");
    Map(x => x.IsRoleActive)
        .Column("IS_ROLE_ACTIVE").CustomType(typeof(BoolToYNType));
    Map(x => x.IsUserActive)
        .Column("IS_USER_ACTIVE").CustomType(typeof(BoolToYNType));

}

Вот NH LINQ, который я использую:

var user = (from u in this.Session.Query<ApplicationUser>()
            where u.UserName.ToUpper() == authenticationRequest.UserName.ToUpper().PadRight(12)
            && u.IsUserActive == true
            && u.IsRoleActive == true
            select new AuthenticatedUser
             {
              RoleId = u.RoleId,
              UserId = u.UserId,
              UserName = u.UserName
             SingleOrDefault();

Это прекрасно работает и выдает следующий SQL

SELECT applicatio0_.ROLE_ID AS col_0_0_,
  applicatio0_.USER_ID      AS col_1_0_,
  applicatio0_.LOGIN_ID     AS col_2_0_
FROM TEST.V_APPLICATION_USER_ROLE applicatio0_
WHERE ((upper(applicatio0_.LOGIN_ID) IS NULL)
AND (:p0                             IS NULL)
OR upper(applicatio0_.LOGIN_ID)       =:p0)
AND
  CASE
    WHEN applicatio0_.IS_USER_ACTIVE='Y'
    THEN 1
    ELSE 0
  END=
  CASE
    WHEN :p1=1
    THEN 1
    ELSE 0
  END
AND
  CASE
    WHEN applicatio0_.IS_ROLE_ACTIVE='Y'
    THEN 1
    ELSE 0
  END=
  CASE
    WHEN :p2=1
    THEN 1
    ELSE 0
  END;
:p0 = 'XXXXX       ' [Type: String (0)],
:p1 = True [Type: Int32 (0)],
:p2 = True [Type: Int32 (0)]

Однако, когда я применяю новые двоичные файлы NH и FNH, генерируется следующий SQL, и я не получаю ожидаемый результат.

SELECT applicatio0_.ROLE_ID AS col_0_0_,
  applicatio0_.USER_ID      AS col_1_0_,
  applicatio0_.LOGIN_ID     AS col_2_0_
FROM TEST.V_APPLICATION_USER_ROLE applicatio0_
WHERE upper(applicatio0_.LOGIN_ID)=:p0
AND
  CASE
    WHEN applicatio0_.IS_USER_ACTIVE='Y'
    THEN 'true'
    ELSE 'false'
  END=
  CASE
    WHEN :p1='true'
    THEN 'true'
    ELSE 'false'
  END
AND
  CASE
    WHEN applicatio0_.IS_ROLE_ACTIVE='Y'
    THEN 'true'
    ELSE 'false'
  END=
  CASE
    WHEN :p2='true'
    THEN 'true'
    ELSE 'false'
  END;
:p0 = 'XXXXX       ' [Type: String (0)],
:p1 = 'True' [Type: String (0)],
:p2 = 'True' [Type: String (0)]

Вот мой конвертер, который всегда работал, но я покажу его только для полноты

public class BoolToYNType : CharBooleanType
{
    /// <summary></summary>
    public BoolToYNType()
        : base(new AnsiStringFixedLengthSqlType(1))
    {
    }

    /// <summary></summary>
    protected override sealed string TrueString
    {
        get { return "Y"; }
    }

    /// <summary></summary>
    protected override sealed string FalseString
    {
        get { return "N"; }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="rs"></param>
    /// <param name="index"></param>
    /// <returns></returns>
    public override object Get(IDataReader rs, int index)
    {
        string code = Convert.ToString(rs[index]);
        if (code == null)
        {
            return false;
        }
        else
        {
            //return StringHelper.EqualsCaseInsensitive(code, TrueString);
            return code == TrueString ? true : false;
        }
    }

    /// <summary></summary>
    public override string Name
    {
        get { return "BoolToYN"; }
    }
}

Я не уверен, что NH или FNH делают это, поэтому я публикую это здесь. Это новая функция или ошибка?

Спасибо Пол

Ответы [ 2 ]

1 голос
/ 09 декабря 2010

ОК, основываясь на запросе, единственная причина, по которой я вижу, что он может потерпеть неудачу, - это чувствительность к регистру при сравнении строк между «True» и «true».Честно говоря, я не понимаю, почему фреймворк переключается с чисел для сравнения на строки.

РЕДАКТИРОВАТЬ: Похоже, что эта проблема могла быть исправлена ​​в большинстве текущего кода.Смотри https://nhibernate.jira.com/browse/NH-2441

1 голос
/ 09 декабря 2010

Вам не нужен пользовательский тип.NHibernate имеет YesNoType (NHibernateUtil.YesNo) из коробки, который делает именно то, что вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...