nHibernate Criteria,尝试按枚举名称排序(按字母顺序而不是按值)

时间:2012-06-14 00:06:04

标签: nhibernate enums sql-order-by criteria

假设我有一个包含状态类型的类,它被定义为枚举,如下所示:

    public class MyObject
    {
        public virtual int Id { get; set; }
        public virtual SomeEntity Data { get; set; }
        public virtual MyStatusEnum Status { get; set; }
    }

    public enum MyStatusEnum
    {
        Active = 1,
        Paused = 2,
        Completed = 3
    }

我通过Fluent nHibernate完成的映射如下所示:

    public class MyObjectMap: ClassMap<MyObject>
    {
        public MyObjectMap()
        {
            this.Table("my_object_table");
            ...
            this.References(x => x.SomeEntity).Column("some_entity_id").Not.Nullable();
            this.Map(x => x.Status).Column("status_type").CustomType<MyStatusEnum>().Not.Nullable();
        }
    }

既然设置已经完成,我的困境就是:

在我的repository类中,我想通过Status属性对所有MyObject实体进行排序,nHibernate将其作为int保留。但是,由于我无法控制的功能,我无法重新排序MyStatusEnum,以便按字母顺序排列枚举值。当我创建我的条件以选择MyObjects列表,并尝试按Status属性对其进行排序时,它按Status的int值排序。

    ICriteria criteria = this.Session.CreateCriteria<MyObject>("obj")
        .AddOrder(Order.Asc("Status"))
        .List()

我真的希望能够通过枚举名称进行排序。任何想法都将不胜感激。

2 个答案:

答案 0 :(得分:1)

如果要在数据库中对其进行排序,则必须按照带有case语句的投影进行排序,但这将无法使用索引,并且可能无法使用,具体取决于您的NHibernate版本(按不在选择中的投影进行排序时会出现错误。

这样的事可能有用:

.AddOrder(Order.Asc(
            Projections.SqlProjection(
                 "CASE {alias}.Status "
                     + "WHEN 1 THEN 0 "
                     + "WHEN 2 THEN 3 "
                     + "WHEN 3 THEN 2 END", 
                  new string[0], new IType[0])))

另一个选项(更好的性能)是在类中添加一个属性,例如StatusOrder,你设置的属性等于枚举中当前状态的相对位置,然后按该字段排序(你可以索引)。

另一个选项是在类上定义一个公式属性(即在映射中指定一个公式),其中公式指定一个值,根据状态进行排序。

答案 1 :(得分:0)

简单的方法是简单地重构枚举,以便值和名称具有相同的顺序:

public enum MyStatusEnum
{
    Active = 1,
    Paused = 3,
    Completed = 2
}

但你总是可以使用List.Sort method来完成这项工作:

enum MyEnum
{
    Alpha,
    Beta,
    Gama
}

static void Main(string[] args)
{
    List<MyEnum> list = new List<MyEnum>()
    {
        MyEnum.Gama,
        MyEnum.Beta,
        MyEnum.Alpha
    };

    list.Sort((x, y) => x.ToString().CompareTo(y.ToString()));
}

NHibernate根据数据库中存储的结果集对结果集进行排序。从你所说的我猜你的枚举被存储为整数,因此你将无法要求SQL Server按名称对它们进行排序,因为SQL Server不知道这些名称。

除非您将枚举存储为字符串,如this SO Question中所述,否则您唯一的选择就是在内存中执行排序,而不是在数据库中执行。