使用 NHibernate 过滤延迟加载集合的内容

发布于 2024-12-10 12:24:09 字数 1137 浏览 0 评论 0 原文

我有一个域模型,其中包括如下内容:

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 项目,因此不会显示用户任何不属于他们并标记为私人的评论。

我尝试做这样的事情:

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

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

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

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

有什么想法可以使用 DetachedCriteria 实现这一点吗?还有其他方法可以实现此目的吗?

I have a domain model that includes something like this:

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; }
}

I have a service layer through which I retrieve these entities, and among the arguments passed to that service layer is who the requesting user is.

What I'd like to do is be able to construct a DetachedCriteria in the service layer that would limit the Comment items returned for a given customer so the user isn't shown any comments that don't belong to them and are marked private.

I tried doing something like this:

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

But this doesn't flow through to the lazy-loaded comments.

I'd prefer not to use a filter because that would require either interacting with the session (which isn't currently exposed to the service layer) or forcing my repository to know about user context (which seems like too much logic in what should be a dumb layer). The filter is a dirty solution for other reasons, too -- the logic that determines what is visible and what isn't is more detailed than just a private flag.

I don't want to use LINQ in the service layer to filter the collection because doing so would blow the whole lazy loading benefit in a really bad way. Lists of customers where the comments aren't relevant would cause a storm of database calls that would be very slow. I'd rather not use LINQ in my presentation layer (an MVC app) because it seems like the wrong place for it.

Any ideas whether this is possible using the DetachedCriteria? Any other ways to accomplish this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

山人契 2024-12-17 12:24:09

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

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

为了最好地适应您当前的模型,我将让您当前进行的调用使实体返回视图模型而不仅仅是实体;

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 Transformer (您可以保留实际注释属性延迟加载,因为您可能不会使用它)

Having the entity itself expose a different set of values for a collection property based on some external value does not seem correct to me.

This would be better handled, either as a call to your repository service directly, or via the entity itself, by creating a method to do this specifically.

To fit in best with your current model though, I would have the call that you currently make to get the the entities return a viewmodel rather than just the entities;

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

And then in your service method (I am making some guesses here)

public PostForUser GetPost(int postId, User requestingUser){

   ...
}

You would then create and populate the PostForUser view model in the most efficient way, perhaps by the detached criteria, or by a single query and a DistinctRootEntity Transformer (you can leave the actual comments property to lazy load, as you probably won't use it)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文