【问题标题】:Linq to NHibernate OrderBy Enum valueLinq 到 NHibernate OrderBy 枚举值
【发布时间】:2012-05-30 15:42:26
【问题描述】:

我有以下枚举,它描述了一个项目的状态和一个代表该项目的对象。

public Enum Status
{
    Sent,
    Received,
    UnderWork,
    Returned
}

public Class Item
{
    public virtual int Id {get;set;}
    public virtual Status CurrentStatus {get;set;}
    public virtual string ItemDescription {get;set;}
    public virtual int ItemNumber {get;set;}
    public virtual DateTime DueDate {get;set;}
}

我需要创建一个查询,我可以在其中选择多个项目并首先按 CurrentStatus 属性排序,然后按 DueDate 属性排序。困难是我想按 CurrentStatus 排序,方法是将所有具有 ReturnDate 状态的项目放在最后,同时按 DueDate 排序,然后仅按 DueDate 排序所有其他项目并忽略 CurrentStatus。

所以下面的数据列表:

ID | CurrentStatus | ItemDescription | ItemNumber | DueDate
-------------------------------------------------------------
1  | Returned      |  Description1   |  123456    | 16/01/2012
2  | Sent          |  Description2   |  234567    | 13/01/2012
3  | Returned      |  Description3   |  345678    | 22/01/2012
4  | Received      |  Description4   |  456789    | 03/01/2012
5  | UnderWork     |  Description5   |  567891    | 10/01/2012
6  | UnderWork     |  Description6   |  678901    | 17/01/2012
7  | Sent          |  Description7   |  789012    | 09/01/2012
8  | Sent          |  Description8   |  890123    | 28/01/2012
9  | Returned      |  Description9   |  901234    | 30/01/2012
10 | Received      |  Description10  |  012345    | 15/01/2012

将使用类似于以下 Linq to NHibernate 的方式进行查询(这给了我一个 QuerySyntaxException:抛出了 'Antlr.Runtime.NoViableAltException' 类型的异常。)请注意在 LINQPad 中使用这个表达式,我可以得到我的结果需要。

var workList = session.Query<Item>()
                .OrderBy(item => item.Status == Status.Returned)
                .ThenBy(item  => item.DueDate)
                .ToList();

我希望按以下顺序获取数据列表:

ID | CurrentStatus | ItemDescription | ItemNumber | DueDate
-------------------------------------------------------------
4  | Received      |  Description4   |  456789    | 03/01/2012
7  | Sent          |  Description7   |  789012    | 09/01/2012
5  | UnderWork     |  Description5   |  567891    | 10/01/2012
2  | Sent          |  Description2   |  234567    | 13/01/2012
10 | Received      |  Description10  |  012345    | 15/01/2012
6  | UnderWork     |  Description6   |  678901    | 17/01/2012
8  | Sent          |  Description8   |  890123    | 28/01/2012
1  | Returned      |  Description1   |  123456    | 16/01/2012
3  | Returned      |  Description3   |  345678    | 22/01/2012
9  | Returned      |  Description9   |  901234    | 30/01/2012

这可以使用 Linq to NHibernate 完成吗?如果是这样,我需要对查询进行哪些更改?我也期待 SKip() 和 Take() 所以我不能只从数据库中提取所有内容。我正在使用 SQL Server 2008 Express、NHibernate 3.3.0.4000 和 Fluent Nhibernate 1.3.0.727。

编辑

只是为了详细说明我希望如何进行排序。我希望将具有返回状态的项目推到列表的底部,并按截止日期对其进行排序。我希望所有其他项目不按状态排序,仅按截止日期排序,因此它们将始终排在退回的项目之前。这是因为任何返回的东西都不再在工作过程中,我希望它被推到列表的末尾。所以在这种情况下,返回以外的状态值是无关紧要的。

【问题讨论】:

    标签: c# nhibernate fluent-nhibernate sql-order-by linq-to-nhibernate


    【解决方案1】:

    这对我有用。 NHibernate 应该如何处理状态并生成 SQL case 语句更明确

    var workList = session.Query<Item>()
        .OrderBy(item => item.CurrentStatus == Status.Returned ? 1 : 0)
        .ThenBy(item => item.DueDate)
        .ToList();
    

    【讨论】:

    • 谢谢,它现在运行良好。不要再为此撕扯我的头发了!
    【解决方案2】:

    您的 LINQ 查询似乎有问题。不确定您是否有意使用它,但您不应该使用.OrderBy(item =&gt; item.Status) 而不是.OrderBy(item =&gt; item.Status == Status.Returned) 吗?这可能会让 NHibernate 的表达式解析器感到困惑。

    您是如何将您的枚举映射到数据库的?到int 列(默认)?还是作为字符串?

    您能解释一下预期的列表吗?考虑到您按状态订购,您不应该首先拥有Sent 项目,然后是Received,然后是UnderWork,最后是Returned?您预期的列表看起来排序不正确。

    【讨论】:

    • 我详细说明了排序应该如何工作,我希望这能澄清我想要发生的事情。我正在使用流利的 nhibernates 自动映射,默认情况下将枚举映射为字符串。我同意是 .OrderBy(item => item.Status == Status.Returned) 导致问题,但我不知道这个 LINQ 表达式是否不受支持,或者我可以改变什么来获得我想要的地方.
    • 感谢您的澄清。我看到你现在想要达到的目标。猜猜 NHibernate 解析器不是那么聪明,但你可以让它更聪明:primordialcode.com/blog/post/…
    • 无论如何,Simen Echholt 的回答似乎为您的问题提供了一个很好的解决方法。看起来比扩展 NHibernate Linq 容易得多,因此如果您的应用程序中没有太多枚举比较,那么使用它可能会更好。
    • 感谢您的链接,今晚将通读。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-12
    • 2011-06-13
    • 2010-09-08
    • 1970-01-01
    • 2019-10-08
    相关资源
    最近更新 更多