1

我正在寻找一种模式的设计解决方案,我将不得不在我正在设计的网站中重复很多次。它将是 ASP.NET MVC 前端,使用 NHibernate 连接到 SQL 数据库的 C# WCF Web 服务。

这是一个社交网站,所以想象一下这里的 facebook 以获得一个概念性的想法。我正在寻找的是一种高效且高效的方式来返回大型数据集的分页结果,例如,用户可能有 150 封电子邮件。我想根据他们所在的页面一次返回 10 个,显然只返回与页面相关的 10 个,而不是必须将所有 150 个项目加载到内存中并且一次只显示 10 个,因为我认为用户体验会与更快的初始加载相比,更改页面的延迟稍长一些会更好。毕竟,您何时查看 6 个月大的电子邮件?通常的情况是你只关心结果的第一页。类似地,用户自上次登录以来可能已经进行了多次交互(例如,您在 facebook 上的通知提要),但我再次只想一次加载 n 个结果,但在这种情况下,您可以点击“显示更多”按钮,然后将获取下一个 N 个结果,用另一个“显示更多”链接显示它们,等等,您可以继续单击,直到到达数据集的末尾。我可以想象它们都使用相同的设计,因为它们在技术上都是分页结果,只是具有不同的 UI 输出和流程。链接等,您可以继续单击,直到到达数据集的末尾。我可以想象它们都使用相同的设计,因为它们在技术上都是分页结果,只是具有不同的 UI 输出和流程。链接等,您可以继续单击,直到到达数据集的末尾。我可以想象它们都使用相同的设计,因为它们在技术上都是分页结果,只是具有不同的 UI 输出和流程。

请记住我的数据检索是使用 NHibernate Queryable 或 Enumerables 的,任何人都可以就一个好的设计提供一些建议吗?我是否想一次性从数据库中加载所有数据,然后使用交互器模式只从服务层返回 N 行,保持列表的其余部分保存在服务器上的内存中,在用户会话上下文中打开,所以如果我做了另一个调用来检索接下来的 N 行,它将保持原位并继续返回 N 行,直到迭代器完成,或者最好从数据库中简单地检索 N 行并返回那些,在会话上下文中不保存任何内容?我可以看到如何从 Queryable 返回前 10 个结果

var results = (from email in emails where email.UserId = userId).Take(10);

但我不确定这有多有效,这是最快的方法吗?而且我不知道如何从某个位置开始,这将始终只返回前 10 个,而不是说第二个 10 或第三个 10 等等。

所以我有点不确定最好的方法是如何进行,并希望从做过类似事情的人那里得到一些指示和建议。牢记我的网站性能至关重要,因此用户体验需要非常清晰和互动,并提供令人耳目一新的新结果。基本上,如果您尝试模拟 facebook 新闻提要/墙 - 您将如何使用上述架构实现它?

谢谢!

4

3 回答 3

4

您可以Skip结合使用Take

var results = (from email in emails where email.UserId = userId)
              .Skip((currentPage - 1) * 10)
              .Take(10);

关于 web 服务:你真的应该让它成为一个无状态的 web 服务。您可以为此使用 ASP.NET Web API。这使您能够构建 RESTful Web 服务。

于 2012-11-23T12:22:21.067 回答
2

我想一键加载所有内容吗...

绝对不是,您只想拉下您需要的记录,而不是您可能需要的记录。

...使用交互器模式仅从服务层返回 N 行,将列表的其余部分保留在服务器上的内存中,在用户会话上下文中打开...

有了这个想法,可扩展性就消失了。

...或者最好简单地从数据库中检索 N 行并返回这些行,在会话上下文中不保留任何内容?

现在你开始走上正轨...

通常,您希望让数据库尽可能多地进行查询,即您不想访问数据库然后必须进一步查询结果(但是,这并不总是可以避免的)。换句话说,您希望将大部分(如果不是全部)繁重的工作委托给数据库。

您提到您正在使用 NHibernate,这是一个非常强大的 ORM。好消息是,在查询优化/缓存数据等方面为您做了很多工作。像现在的大多数 ORM 一样,NHibernate 对其查询使用延迟执行,所以请注意诸如过早访问数据库和选择何时急切加载数据而不是执行多个查询。NHibernate 有很多东西要学,如果你还没有,那么在深入研究之前花时间阅读它是值得的,从长远来看,它将为你节省很多麻烦。

牢记我的网站性能至关重要,因此用户体验需要非常清晰和互动,并提供令人耳目一新的新结果

就性能而言(我假设您的意思是页面加载速度),您只想对您的网站进行 ajaxify 处理,即加载页面需要加载的内容,将其余部分拉到后台并动态更新页面。要实现“刷新新结果”部分,您需要查看轮询服务器并拉取新数据。我很确定 Facebook 使用了一种称为长轮询的技术这实际上使服务器在一定时间内保持活动请求打开,因此数据似乎“立即”发生。轮询是一个完全不同的球类游戏,它是关于平衡服务器负载与数据需要多么“新鲜” - 这是您需要自己决定的事情,而答案通常取决于数据类型与服务器的硬件能力相比。

于 2012-11-23T12:54:02.847 回答
0

有一些关于它的链接(像这样),但我喜欢这个人的方法。我不知道我是否会使用他的 PagedQueryable,但他的IPageableIPagedEnumerablePagedEnumerable真的很有趣。此外,他的项目介绍页面可能会为您提供一些有关如何滚动自己的分页的想法。

于 2012-11-23T14:58:35.580 回答