如何使用枚举类型的显示名称对nHibernate中的枚举列进行排序

时间:2017-08-24 08:15:24

标签: c# .net nhibernate

我有一张表Email,其中有一列EmailTypeEmailType是nHibernate中的枚举,在DB中存储为int。我还有扩展方法来获取电子邮件类型的名称:

namespace Email
{
    public enum EmailType : int
    {
        PasswordReset = 0,
        EmailVerification = 1,
        AccountCreation = 2
    };

    public static class EmailType Extension
    {
      public static string Name(this EmailType self)
      {
        switch (self)
        {
          case EmailType.PasswordReset :
            return "Password Reset";
          case EmailType.EmailVerification :
            return "Email Verification";
          case EmailType.AccountCreation :
            return "Account Creation";
          default:
            return null;
        }
      }
    }
}

然后我可以使用EmailType.PasswordReset.Name()

获取枚举的名称

我通过创建nHibernate标准来获取电子邮件列表:

var criteria = session.CreateCriteria<Email>();
criteria.SetFirstResult(startIndex).SetMaxResults(maxResults);
criteria.AddOrder(Order.Asc("EmailType"));
return criteria.List<Email>();

问题在于它使用存储在DB中的EmailType int对行进行排序。有什么方法可以使用EmailType.PasswordReset.Name()枚举的EmailType扩展方法对枚举名称进行排序吗?

2 个答案:

答案 0 :(得分:0)

由于您的枚举(在本例中)按字母顺序排列将由2,1,0表示,您可以按相反的顺序订购EmailType,这样可以为您提供所需的内容。

criteria.AddOrder(Order.desc("EmailType"));

然而,正如你所说,&#34;这是巧合&#34;。

它无法对枚举名称进行排序的原因是它不知道它们是什么,因此您需要找到一种方法来表达它。有两个:

一种方法是添加一个计算字段,将枚举值转换为名称。我已经用其他数据库做了这个,我相信@Formula就是你在Hibernate中使用的。

另一种方法是在数据库中创建另一个包含枚举数和枚举值的表。然后链接查询中的两个表,以便返回枚举值。

在任何一种情况下,您都会对新字段应用排序。

答案 1 :(得分:0)

我遇到了同样的问题,我找到了一种使用投影的方法

QueryOver<TRoot, TSubType>.OrderBy(IProjection projection)

queryOver
    .OrderBy(GetOrderByEnumProjection<TSubType, MyEnum>(x => x.EnumProperty, GetAllMyEnumValuesSortedByDisplayName(CultureInfo.CurrentCulture)));

private static IProjection GetOrderByEnumProjection<TObject, TEnum>(Expression<Func<TObject, object>> enumProperty, IReadOnlyList<TEnum> enumValues)
    where TEnum : Enum
{
    int index = enumValues.Count - 1;

    TEnum enumValue = enumValues[index];

    IProjection elseProjection = GetConditional(enumProperty, enumValue, index, Projections.Constant(-1));

    for (index = enumValues.Count - 2; index >= 0; index--)
    {
        enumValue = enumValues[index];

        elseProjection = GetConditional(enumProperty, enumValue, index, elseProjection);
    }

    return elseProjection;
}

private static IProjection GetConditional<TObject, TEnum>(Expression<Func<TObject, object>> enumProperty, TEnum value, int sortIndex, IProjection elseProjection)
    where TEnum : Enum
{
    return Projections.Conditional(
        Restrictions.Eq(Projections.Property<TObject>(enumProperty), value),
        Projections.Constant(sortIndex),
        elseProjection);
}

(您可以在此处找到有关结果 SQL 的更多详细信息:Adding more than one condition in Projection.Conditionals for queryover。)