不确定如何使用LINQ实现nHibernate的特定扩展

本文关键字:扩展 nHibernate 实现 何使用 LINQ 不确定 | 更新日期: 2023-09-27 17:57:40

在相当受欢迎的ayende.com网站的博客文章中。有一节以一种非常具体的方式吸引了我的眼球。

在帖子的末尾,他发表了一条评论,引用了网站的话

对于"好吧,那么我如何应用安全过滤"之类的问题,我给出的答案是,你将其放入一个扩展方法中,然后做这样的事情:

var query = 
  (
        from post in session.Query<Post>()
        where post.DueDate > DateTime.Now 
        select post
   )
   .FilterAccordingToUserPermissions(CurrentUser)
   .ToList();

老实说,我真的很喜欢这种方法。对我来说,它看起来很干净。但由于我对扩展方法或抽象方法缺乏经验和知识,我似乎无法复制它。

var query = ( from post in session.Query<Post>() ...

这告诉我正在使用的对象是NHibernate.Linq.Query<T>对象。我在我的项目中主要使用QueryOver<T>,目的是将它们投影到Futures,但我跑题了。。。

我意识到这是非常模糊的,根本不是一个非常一致的请求——但我想知道是否有人愿意发布一个如何实现这个示例代码的示例。

以下是我不明白的地方;

  1. 我不知道如何扩展Query<T>QueryOver<T>对象
  2. 如果我确实扩展了对象,我不知道如何使该扩展影响/过滤数据库查找
  3. 如果我能够影响数据库查找,我不明白它将如何影响性能
  4. 我真的不明白CurrentUser是从哪里来的。在我看来,这需要另一次数据库访问才能获得,这再次违背了nhprof和我读过的大多数书一直告诉我的(不要为一个操作进行多次访问)

第三点是我最困惑的一点。我唯一能想到的是,这个方法接受查询并运行它,然后过滤它,然后返回结果。对我来说,这似乎违背了直觉(这似乎与我在ayende.com/博客网站上看到的很多东西相悖,因为它继承地建议了很多非必要的数据库调用)

你知道了。我很无知,我确实理解,对于你们中一些更有经验的人来说,这是一个非常愚蠢的问题。但我太新了,无法理解一切,我花了5周的大部分时间试图做到这一点。

不确定如何使用LINQ实现nHibernate的特定扩展

是的,你是对的,这个问题有点模糊,但我会尽力解决你的观点。

1) 您并没有真正扩展Query对象。你要写的扩展实际上是反对IQueryable的,所以…

    public static IQueryable<Post> MySecurityExtension(this IQueryable<Post> repository, string currentUser)
    {
        return repository.Where(p => p.User == currentUser);
    }

显然,您的安全标准会比这更复杂。

2) 扩展方法允许您将附加条件添加到传入的IQueryable中。然后,当执行该queryable时,NH查询引擎会将该附加条件内置到sql中。

3) 性能显然与您编写的查询有关,更复杂的查询执行速度会较慢。然而,扩展方法本身并没有对性能造成影响。重要的是要理解,在构建整个查询之前,查询是不执行的。这通常由触发。ToList()、Single()、First()或其他实际枚举可查询对象的语句。

4) CurrentUser来自您,可能必须事先从数据库中获取。但在应用程序中,您可能无论如何都要这样做。

扩展方法实际上与NHibernate无关。它只用于过滤(或"将安全策略应用于")NHibernate查询返回的IEnumerable<Post>

换句话说,NHibernate将返回一个可枚举的实体列表(来自数据库),扩展方法将过滤该列表。没有提供FilterAccordingToUserPermissions的实现,所以我们不能对它说太多,包括它是否会表现不佳。

扩展方法将在静态类中定义,如下所示:

public IEnumerable<Post> FilterAccordingToUserPermissions(this IEnumerable<post> list, CurrentUser user)
{
    // implementation
}

别忘了,没有愚蠢的问题:)