按条件列选择实体,并按多个条件澄清它

时间:2014-12-15 11:00:02

标签: nhibernate many-to-many criteria queryover

按条件列选择实体,并按多个条件澄清

我遵循了类(实体)的结构:

class Order {
   ...
   public virtual long OrderId {get; set;}
   public virtual boolean ForFavorites {get; set;}
   public virtual User Owner {get; set;}
   ...
}
class User {
   ...
   public virtual long UserId { get; set; }
   public virtual List<User> Favorites {get; set;}
   public virtual List<User> FavoritesOrderers {get; set;}
   ...
}

如何编写QueryOver或Criteria以获取所有订单:

  • 订单不是ForFavorites AND
  • 的标记
  • 订单被标记为ForFavorites而某些用户在订单中.Owner.Favorites?

相反的方式:

如何撰写QueryOver或条件以选择我的收藏夹中Order.Owner的所有订单?

- 更新:添加Fluent Mapping

我的映射:

class OrderMap:ClassMap<Order> {

    public OrderMap(){
        Id(x=>x.OrderId).GeneratedBy.Identity();
        Map(x => x.ForFavorites);
        References(x => x.Owner, "UserId");
        ...
    }
}

class UserMap:ClassMap<User> {
    public UserMap() {
        Id(x => x.UserId).GeneratedBy.Assigned();
        HasManyToMany(x => x.Favorites)
            .AsBag()
            .LazyLoad()
            .Table("Favorites")
            .ParentKeyColumn("UserId")
            .ChildKeyColumn("FavoriteId")
            .Cascade.All();
        HasManyToMany(x => x.FavoritesOrderers)
            .AsBag()
            .LazyLoad()
            .Table("FavoriteOrderers")
            .ParentKeyColumn("UserId")
            .ChildKeyColumn("FavoriteId")
            .Cascade.All();
        ...
    }
}

- 更新:添加一些SQL

SQL可能是这样的:

:userId是收藏用户的ID

SELECT * 
FROM [Order] o
JOIN [User] u ON o.owner = u.userId
WHERE (
    (o.ForFavorites = false) || 
    (o.ForFavorites = true && :userId IN
        (SELECT favoriteId FROM [Favorites] f WHERE (f.UserId = u.userId))
))

是否有一些其他变体具有更好的性能?..

相反的方式:

SELECT *  
FROM [Order] o
JOIN [User] u ON o.owner = u.userId
INNER JOIN [FavoriteOrderers] fo ON fo.favoriteId=u.userId
WHERE (fo.userId = :userId)

2 个答案:

答案 0 :(得分:1)

我对你的映射做了一些假设,但希望这会有所帮助:

对于第一个查询,可能是这样的:

session.QueryOver<Order>()
    .JoinQueryOver(o => o.Owner)
    .Where(
        Restrictions.Or(
            Restrictions.Where<Order>(o => !o.ForFavorites),
            Restrictions.And(
                Restrictions.Where<Order>(o => o.ForFavorites),
                Subqueries.In( 
                    userId,
                    QueryOver.Of<Favorite>()
                        .Where(f => f.UserId = userId)
                        .Select(f => f.FavoriteId)
                        .DetachedCriteria))))
    .List<Order>();

我将联接省略为User,因为它未被使用(并且您说您希望所有Order符合条件。

您的第二个查询可能如下所示:

session.QueryOver<Order>()
    .JoinQueryOver(o => o.Owner)
    .JoinQueryOver<FavoriteOrderers>(u => u.FavoriteOrderers)
        .Where(fo => fo.UserId == userId)

答案 1 :(得分:1)

经过良好的回复,我发现了我的解决方案,因为在回复中海报使用自己的映射假设, 在我的情况下哪些不对,但可能会更好。

session.QueryOver<Order>()
    .JoinAlias(o => o.Owner, () => owner)
    .Where(
        Restrictions.Or(
            Restrictions.Where<Order>(o => !o.ForFavorites),
            Restrictions.And(
                Restrictions.Where<Order>(o => o.ForFavorites),
                Subqueries.In( 
                    userId,
                    QueryOver.Of<User>()
                        .Where(f => f.UserId = owner.UserId)
                        .JoinQueryOver<User>(u => u.Favorite, () => fav)
                        .Select(f => f.FavoriteId)
                       .DetachedCriteria))))
    .List<Order>();