5

我目前的项目正在使用 NHibernate 3.0b1 和NHibernate.Linq.Query<T>()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; }
}

ATicket有一个TicketAction描述其历史的集合。TicketAction子类型包括CreateActionReassignActionCloseAction等。所有票证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<T>()方法导致 aNotSupportedException被抛出。我可以使用 ICriteria 来代替吗?

4

2 回答 2

2

尝试这样的事情。它是未编译的,但它应该可以工作,IEnumerable<TicketAction> Actions并且Person TakenBy永远不会为空。如果您在票证构造函数中将其设置为一个空列表,这将解决空值问题。

如果您在 TicketAction 中添加对 Ticket 对象的引用,您可以执行以下操作:

ICriteria criteria = _session.CreateCriteria(typeof(CreateAction))
   .Add(Expression.Eq("TakenBy.Name", createdByName));

var actions = criteria.List<CreateAction>();

var results = from a in criteria.List<>()
   select a.Ticket;

根据我的经验,当列表位于对象端时,nhibernate 在列表方面存在标准问题 - 例如您的情况。当它是输入端的值列表时,您可以使用 Expression.Eq。我总是不得不通过 linq 找到解决这个限制的方法,在那里我尽可能地过滤掉初始结果集,然后用 linq 再次过滤以获得我需要的东西。

于 2010-11-01T14:10:18.890 回答
0

支持 OfType。我不确定 ToUpper 是不是,但由于 SQL 忽略大小写,这并不重要(只要您不在内存中运行查询......)。这是来自 nHibernate.LINQ 项目的工作单元测试:

var animals = (from animal in session.Linq<Animal>()
               where animal.Children.OfType<Mammal>().Any(m => m.Pregnant)
               select animal).ToArray();
Assert.AreEqual("789", animals.Single().SerialNumber);

也许您的查询应该更像以下内容:

var animals = (from ticket in session.Linq<Ticket>()
               where ticket.Actions.OfType<CreateAction>().Any(m => m.TakenBy.Name.Contains("john"))
               select ticket).ToArray();
于 2010-11-03T07:45:39.370 回答