流畅的NHibernate使用Linq过滤子集合

时间:2012-10-05 11:34:27

标签: linq nhibernate fluent-nhibernate

我正在尝试检索根聚合及其子聚类,对子集合应用日期过滤器。

CREATE TABLE Shop
(
    Id int
)

CREATE TABLE Order
(
    ShopId int,
    OrderDate datetime
)

当然,子对象没有ShopId属性来避免双向引用:

class Shop
{
    int Id { get; set; }
    List<Order> { get; set; }
}

class Order
{
    DateTime OrderDate { get; set; }
}

FNHB映射看起来像这样:

public ShopMap()
{
    this.Table("SHOP");
    this.Id(x => x.Id).Column("ID");
    this.HasMany(x => x.Orders).Table("ORDER").KeyColumn("SHOP_ID");
}

public OrderMap()
{
    this.Table("ORDER");
    this.Map(x => x.OrderDate);
}

我正在尝试检索某个商店及其订单在某些日期之间放置,给定参数shopId, fromDate, toDate,我试过这个,但它会抛出异常:

Session.Query<Shop>().Where(shop => shop.Id == shopId)
.FetchMany(
    shop => shop.Orders.Where(
        order => order .OrderDate >= fromDate && order.OrderDate <= toDate));

这可以在不使用Magic Strings(NHb标准,HQL等)的情况下实现,优选使用简单的Linq查询吗?

2 个答案:

答案 0 :(得分:3)

您需要在联接的ON子句中显示日期条件,而对shopId的检查应该在WHERE子句上。试试这个:

Shop shopAlias = null;
Order orderAlias = null;

ICriterion dateCriterion = Restrictions.Where<Order>
    (o => o.OrderDate >= fromDate && o.OrderDate <= toDate);

var query =
    QueryOver.Of(() => shopAlias).Left.JoinAlias(
    () => shopAlias.Orders, () => orderAlias, dateCriterion).Where
    (s => s.Id == shopId);
var result = query.GetExecutableQueryOver(Session).SingleOrDefault();

答案 1 :(得分:0)

使用Query无法解决问题,但可以使用QueryOver执行此操作:

Shop shopAlias = null;
var existing = QueryOver.Of<Order>()
                        .Where(x => x.OrderDate >= fromDate)
                        .And(x => x.OrderDate <= toDate)
                        .And(x => x.Shop.Id == shopAlias.Id)
                        .Select(x => x.Shop);

result = Session.QueryOver<Shop>(() => shopAlias)
                .Fetch(x => x.Orders).Eager
                .WithSubquery.WhereNotExists(existing)
                .List();

这样的事情应该有用。

http://www.philliphaydon.com/2011/01/revisiting-exists-in-nhibernate-3-0-and-queryover/