我正在为.net中的项目构建一个显示篮球锦标赛支架的网页。每个团队在他们的名字旁边都有一个按钮,当点击它时,它们会在支架中前进,他们所扮演的团队会移动到失败者支架(它是双重消除)。你可以拖动括号和缩放,所以我决定使用ajax调用更新赢家和输家,然后显示结果而不回发,刷新页面和丢失缩放/拖动位置。
在为64支队伍选择获胜者时,ajax调用工作非常快,并立即返回结果。在我完成部分操作之后,该调用需要几秒钟,然后最终返回错误,这意味着更新未完成,并且我没有获得任何返回括号结果。当我在另一个选项卡中打开该站点的另一个页面时,需要一段时间才能加载,最终我收到一条错误,表明我无法查询数据库。
这是流程的代码/流程:
- 点击获奖团队时,会调用:
$.ajax({
type: 'POST',
url: '/Handlers/TestHandler.ashx',
data: { 'tournamentID': tournamentID },
dataType: "json",
success: function (response) {
switch (response[0].toString().toUpperCase()) {
case "SUCCESS":
PopulateBracket(response);
break;
default:
alert('Error setting winner.');
break;
}
},
error: function () {
alert('Error setting winner.');
}
});
- 来自调用的结果以json的形式返回,并使用更新的结果填充括号。
- 在处理程序中,我创建了一个我创建的数据访问层类的新实例,以便更轻松地查询我的数据库。
- 然后执行必要的逻辑以确定团队的去向。
- 我尝试为获胜者和输家执行插入记录,并在一个查询中查询括号结果。如果失败,我会对记录执行更新并返回括号结果(如果有人正在更新匹配,我认为尝试插入是最容易的,并且在失败时执行更新而不是在匹配上执行选择以查看是否存在行以了解是执行插入还是更新。
- 这是处理程序如何工作的简化版本(我在" SUCCESS"或" ERROR"到返回的json,以便我知道是否存在问题 - 请参阅上面ajax调用中的switch语句:
DAL dl = new DAL();
DataTable dt = dl.GetDataTable("INSERT; SELECT;");
if dt is null or empty, dt = dl.GetDataTable("UPDATE; SELECT;");
context.Response.Write(serializer.Serialize(dt))
- 这是数据访问层(DAL)的工作方式:
public class DAL
{
String cnnStr;
public DAL()
{
cnnStr = ConfigurationManager.ConnectionStrings["sqlConnection"].ConnectionString;
}
public DataTable GetDataTable(String sql, ref String error)
{
DataTable dt = new DataTable();
using (SqlConnection conn = new SqlConnection(cnnStr))
{
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
using (SqlDataAdapter adapter = new SqlDataAdapter(cmd))
{
try
{
adapter.Fill(dt);
}
catch (Exception e)
{
error = e.Message;
if (debugMode)
Console.Write(e.Message);
}
}
}
}
return dt;
}
所以...从我读过的内容来看,我正在数据访问层中正确关闭连接。我将数据库调用最小化为每个选择一个匹配的赢家只有两个。我正在等待ajax呼叫完成,然后再发起另一个呼叫(我有一个不可关闭的加载弹出窗口,当呼叫完成后,一旦呼叫完成就会消失 - 成功与否)。括号还会填充新结果,这是呼叫成功的另一个指示。
为什么在填写一些支架之后会发生这种情况?如果我进入托管解决方案的控制面板,我使用并重新启动网站并回收应用程序池,一分钟后一切似乎都能正常工作。
是不是我以某种方式达到数据库连接的最大池大小?关于如何发生这种情况的任何想法?
更新
我没有花时间研究这个问题,因为我在一个试图通过javascript计时器和ajax调用每隔30秒刷新一次结果的页面上有类似的问题。相反,我创造了一个有效的替代品。它可能不是最优雅的解决方案,但它有效。
这是:
- 在页面上放置一个更新面板。
- 在更新面板中放置两个隐藏字段。一个用于填充括号的数据(让我们称之为' HiddenBracketDataBox')和一个用于提交比赛的获胜者(让我们说#' 39; s称为' HiddenSubmissionBox')。
- 在Page_Load中的代码隐藏文件中,我运行了一些检查HiddenSubmissionBox值的代码。如果有效(非空白,格式正确等),则触发代码将提交内容发布到数据库。如果HiddenSubmissionBox为空,则不会触发任何内容。在函数结束时,我清除了HiddenSubmissionBox字段,因此尝试重新提交时没有问题。
- 在这个函数之后,我有一个查询括号数据的函数(重要的是这是在提交代码之后,所以我拿起提交并获得包含最近提交的最新数据)。此函数返回我可以转储到HiddenBracketDataBox字段的数据。
- 在我的javascript的$(document).ready(function(){};部分中,我调用了一个函数(让我们称之为' PopulateData')通过从HiddenBracketDataBox字段中提取数据,处理数据并将其放在正确的括号位置来填充括号数据。
- 调用PopulateData后,执行以下操作(这是为了确保刷新更新面板将填充括号):
try {
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
} catch (e) {}
function EndRequestHandler(sender, args) {
PopulateData();
}
- 最后,最后一块拼图是点击获胜团队时发生的事情。为此,我将HiddenSubmissionBox的值设置为指示哪个团队作为获胜者提交以及支架中的什么位置。这是由Page_Load代码获取并发布到数据库的内容。设置HiddenSubmissionBox值后,我调用
__doPostBack('UpdatePanel1', 'REFRESH');
使更新面板刷新,然后调用提交功能并获取发布到隐藏字段的括号结果。
就是这样。就像我说的,不是最优雅但它的作用。我经历了两次超过32次团队选举的选手,从未遇到任何问题。在我最多可能通过一秒钟和一点点之前。这个解决方案让.net处理显然缺少的清理,并保持不刷新的页面的外观。
祝你好运,我们都指望你。希望这有助于某人。