我在MSSQL数据库中有一个表,我有一个ASPX页面,我需要按降序将所有新行推送到页面。我发现this awesome tutorial正在使用SignalR和SqlDependency,它只显示了我在线时添加的前一行的最后一行,这样做是因为它有一个span元素来显示数据,每次都显示数据覆盖这个范围,所以我修改了JavaScript代码以附加新数据并且工作正常。
现在的问题是,当我第一次刷新页面时,我将获得两次新行,如果我再次刷新页面,我将获得三行的新行......依此类推。
唯一的解决方案是关闭应用程序并再次重新打开它,它看起来像重置IIS。
那么,我该怎么做才能避免在线节目中重复数据?
答案 0 :(得分:0)
这不是一个SignalR问题,因为上面提到的教程有一系列的错误,最明显的是它不断创建 SqlDependency
个实例,但随后它会在没有取消订阅的情况下将它们删除OnChange
事件。你应该首先添加这样的东西:
SqlDependency dependency = sender as SqlDependency;
dependency.OnChange -= dependency_OnChange;
在调用事件处理程序中的 SendNotifications
之前。检查this以获得一些灵感。
更新(之前的答案不完全准确,但保留上下文)
这里的主要问题是这种技术从Web窗体页面的实例内部创建了一种自动重新生成SqlDependencies
的无限序列,这使得一旦页面完成渲染就无法访问它们。这意味着,一旦您的页面生命周期完成并呈现页面,即使创建的页面实例已完成其循环,依赖链仍然保持活动并继续工作。即使无法访问,事件处理程序也会使页面实例保持活动状态,从而导致内存泄漏。
你可以控制它的唯一方法实际上是在其他地方生成这些链,例如在静态类型中你可以调用传递一些唯一标识符(可能是页面名称和用户名的组合?这取决于你的逻辑)。在第一次调用时,它将执行当前代码中当前发生的操作,但只要您使用相同的参数执行另一个调用,它就什么都不做,因此先前创建的链将继续作为唯一通知,没有重复调用
这只是一个建议,会有很多可能的解决方案,但你需要了解原始问题以及如果你不这样做,那么几乎不可能删除那些自动重新生成的依赖链。找到一种方法来跟踪它们并仅在必要时创建它们。我希望这部分是清楚的。
PS:这种行为非常类似于你有时会遇到事件处理程序泄露并保留应该被杀死的活动对象,这就是用前面的答案欺骗我的原因。它在某种程度上是一个类似的问题(泄漏的对象),但有一个完全不同的原因。您所遵循的教程并未阐明这一点,并将您带到幻像代码继续执行且内存丢失的情况。
答案 1 :(得分:0)
我明白了,虽然我绝对不喜欢这种方式,但我在Global.asax文件中声明了一个静态成员,并在Page_Load事件中检查了它的值,如果是,则不运行新实例SqlDependency,否则运行它。
if (!Global.PageIsFired)
{
Global.PageIsFired = true;
SqlDependency.Stop(ConfigurationManager.ConnectionStrings["db"].ConnectionString);
SqlDependency.Start(ConfigurationManager.ConnectionStrings["db"].ConnectionString);
SendNotifications();
}
亲爱的@Wasp,
你的上一次更新帮助我理解了这个问题,所以非常感谢你的时间和迅速的支持。
亲爱的@dyatchenko, 非常感谢您的评论,它也非常有用。