【问题标题】:Filter contents of lazy-loaded collection with NHibernate使用 NHibernate 过滤延迟加载集合的内容
【发布时间】:2011-10-16 21:21:00
【问题描述】:

我有一个包含以下内容的域模型:

public class Customer : EntityBase<Customer>, IAggregateRoot
{
    public IList<Comment> Comments { get; set; }
}

public class Comment : EntityBase<Comment>
{
    public User CreatedBy { get; set; }
    public bool Private { get; set; }
}

我有一个服务层,通过它我可以检索这些实体,传递给该服务层的参数是请求用户是谁。

我想做的是能够在服务层中构造一个DetachedCriteria,这将限制为给定客户返回的Comment 项目,因此不会向用户显示任何不属于的 cmets并标记为私有。

我试着做这样的事情:

criteria.CreateCriteria("Comments")
    .Add(Restrictions.Or(Restrictions.Eq("Private", false),
                         Restrictions.And(Restrictions.Eq("Private", true),
                                          Restrictions.Eq("CreatedBy.Id", requestingUser.Id))));

但这不会流向延迟加载的 cmets。

我不希望使用过滤器,因为这将需要与会话交互(当前未暴露给服务层)或强制我的存储库了解用户上下文(这在什么应该是哑层)。由于其他原因,过滤器也是一个肮脏的解决方案——确定什么可见什么不可见的逻辑比私有标志更详细。

我不想在服务层使用 LINQ 来过滤集合,因为这样做会以非常糟糕的方式破坏整个延迟加载的好处。 cmets 不相关的客户列表将导致数据库调用风暴,这将非常缓慢。我宁愿不在我的表示层(一个 MVC 应用程序)中使用 LINQ,因为它似乎不适合它。

任何想法是否可以使用DetachedCriteria?还有其他方法可以做到这一点吗?

【问题讨论】:

    标签: nhibernate detachedcriteria


    【解决方案1】:

    让实体本身根据某些外部值为集合属性公开一组不同的值对我来说似乎不正确。

    这会更好地处理,可以直接调用您的存储库服务,也可以通过实体本身创建一个专门执行此操作的方法。

    不过,为了最适合您当前的模型,我会调用您当前的调用来让实体返回视图模型,而不仅仅是实体;

    public class PostForUser
    {
        public Post Post {get; set;}
        public User User {get; set;}
        public IList<Comment> Comments}
    }
    

    然后在你的服务方法中(我在这里做一些猜测)

    public PostForUser GetPost(int postId, User requestingUser){
    
       ...
    }
    

    然后,您将以最有效的方式创建和填充 PostForUser 视图模型,可能是通过分离条件,或者通过单个查询和 DistinctRootEntity 转换器(您可以将实际的 cmets 属性留给延迟加载,因为您可能赢了不要使用它)

    【讨论】:

    • 我实际上是在 MVC 应用程序中构建 ViewModel,但您的回答让我想到了一些我以前没有想到的东西——在实体本身上添加一个 CommentsForUser(User user) 方法,这将返回一个 LINQ 过滤的集合厘米。作为一个领域实体,并且这个过滤概念是领域的重要组成部分,我不认为这是关注点的重叠。
    • 是的,这就是我实际要做的方式。但是,我不会使用 LINQ 过滤 cmets 属性,我会调用存储库以仅获取用户的 cmets(这样您就不必从数据库中加载所有 cmets 来仅选择几个)跨度>
    • 但是,要做到这一点,您需要使用 DI 设置存储库接口,以便您的域可以与数据层分开,但这是另一回事...
    • 是的,如果可能的话,我宁愿将存储库保留在域对象之外(即使 NHibernate 没有简单的 POCO 这样的东西)。如果性能在路上失控,我会记住这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-26
    • 1970-01-01
    • 2011-07-16
    • 2011-08-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多