不确定如何使用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
,但我跑题了。。。
我意识到这是非常模糊的,根本不是一个非常一致的请求——但我想知道是否有人愿意发布一个如何实现这个示例代码的示例。
以下是我不明白的地方;
- 我不知道如何扩展
Query<T>
或QueryOver<T>
对象 - 如果我确实扩展了对象,我不知道如何使该扩展影响/过滤数据库查找
- 如果我能够影响数据库查找,我不明白它将如何影响性能
- 我真的不明白
CurrentUser
是从哪里来的。在我看来,这需要另一次数据库访问才能获得,这再次违背了nhprof和我读过的大多数书一直告诉我的(不要为一个操作进行多次访问)
第三点是我最困惑的一点。我唯一能想到的是,这个方法接受查询并运行它,然后过滤它,然后返回结果。对我来说,这似乎违背了直觉(这似乎与我在ayende.com/博客网站上看到的很多东西相悖,因为它继承地建议了很多非必要的数据库调用)
你知道了。我很无知,我确实理解,对于你们中一些更有经验的人来说,这是一个非常愚蠢的问题。但我太新了,无法理解一切,我花了5周的大部分时间试图做到这一点。
是的,你是对的,这个问题有点模糊,但我会尽力解决你的观点。
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
}
别忘了,没有愚蠢的问题:)