如何使用 NHibernate ICriteria API 表达此 LINQ 查询?
我当前的项目使用 NHibernate 3.0b1 和 NHibernate.Linq.Query
API。我非常熟悉 LINQ,但我完全没有 HQL 或 ICriteria API 的经验。 IQueryable API 不支持我的一个查询,因此我认为我需要使用以前的 API 之一 - 但我不知道从哪里开始。
我尝试在网上搜索 ICriteria 的良好“入门”指南,但我发现的唯一示例要么太简单而无法应用于此处,要么太高级而无法理解。如果有人有一些好的学习材料可以传递,将不胜感激。
无论如何,我查询的对象模型看起来像这样(大大简化,省略了不相关的属性):
class Ticket {
IEnumerable<TicketAction> Actions { get; set; }
}
abstract class TicketAction {
Person TakenBy { get; set; }
DateTime Timestamp { get; set; }
}
class CreateAction : TicketAction {}
class Person {
string Name { get; set; }
}
Ticket
有一个描述其历史记录的 TicketAction
集合。 TicketAction
子类型包括 CreateAction
、ReassignAction
、CloseAction
等。所有票据都有一个 CreateAction
> 在创建时添加到此集合中。
此 LINQ 查询正在搜索由具有给定名称的人创建的票证。
var createdByName = "john".ToUpper();
var tickets = _session.Query<Ticket>()
.Where(t => t.Actions
.OfType<CreateAction>()
.Any(a => a.TakenBy.Name.ToUpper().Contains(createdByName));
OfType
方法会引发 NotSupportedException
。我可以使用 ICriteria 来完成此操作吗?
My current project is using NHibernate 3.0b1 and the NHibernate.Linq.Query<T>()
API. I'm pretty fluent in LINQ, but I have absolutely no experience with HQL or the ICriteria API. One of my queries isn't supported by the IQueryable API, so I presume I need to use one of the previous APIs -- but I have no idea where to start.
I've tried searching the web for a good "getting started" guide to ICriteria, but the only examples I've found are either far too simplistic to apply here or far too advanced for me to understand. If anyone has some good learning materials to pass along, it would be greatly appreciated.
In any case, the object model I'm querying against looks like this (greatly simplified, non-relevant properties omitted):
class Ticket {
IEnumerable<TicketAction> Actions { get; set; }
}
abstract class TicketAction {
Person TakenBy { get; set; }
DateTime Timestamp { get; set; }
}
class CreateAction : TicketAction {}
class Person {
string Name { get; set; }
}
A Ticket
has a collection of TicketAction
describing its history. TicketAction
subtypes include CreateAction
, ReassignAction
, CloseAction
, etc. All tickets have a CreateAction
added to this collection when created.
This LINQ query is searching for tickets created by someone with the given name.
var createdByName = "john".ToUpper();
var tickets = _session.Query<Ticket>()
.Where(t => t.Actions
.OfType<CreateAction>()
.Any(a => a.TakenBy.Name.ToUpper().Contains(createdByName));
The OfType<T>()
method causes a NotSupportedException
to be thrown. Can I do this using ICriteria instead?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
尝试这样的事情。它是未编译的,但只要
IEnumerable就应该可以工作。 Actions
和Person TakenBy
永远不会为空。如果您在票证构造函数中将其设置为空列表,则可以解决空值问题。如果您在 TicketAction 中添加对 Ticket 对象的引用,您可以执行以下操作:
根据我的经验,当列表位于对象端时,nhibernate 在处理列表时会遇到标准问题 - 就像您的情况一样。当输入端是值列表时,可以使用Expression.Eq。我总是必须通过 linq 找到解决此限制的方法,我会尽可能地过滤出初始结果集,然后使用 linq 再次过滤以获得我需要的内容。
try something like this. It's uncompiled, but it should work as long as
IEnumerable<TicketAction> Actions
andPerson TakenBy
is never null. If you set it to an empty list in the ticket constructor, that will solve a problem with nulls.If you add a reference to the Ticket object in the TicketAction, you could do something like this:
In my experience, nhibernate has trouble with criteria when it comes to lists when the list is on the object side - such as is your case. When it is a list of values on the input side, you can use Expression.Eq. I've always had to find ways around this limitation through linq, where I get an initial result set filtered down as best as I can, then filter again with linq to get what I need.
支持 OfType。我不确定 ToUpper 是不是,但由于 SQL 忽略大小写,这并不重要(只要您不在内存中运行查询...)。这是来自 nHibernate.LINQ 项目的工作单元测试:
也许您的查询应该类似于以下内容:
OfType is supported. I'm not sure ToUpper is though, but as SQL ignores case it does not matter (as long as you are not also running the query in memory...). Here is a working unit test from the nHibernate.LINQ project:
Perhaps your query should look more like the following: