过去几天我们一直在处理一个错误,所以我们创建了一个小页面(快速和脏的编程,我提前道歉)连接到数据库,检查文档是否存在,并显示一些数据与该文件有关。如果存在异常,则会发送包含异常信息和一些日志数据的电子邮件。
这是代码的简化版本(以下简短说明):
namespace My.Namespace
{
public partial class myClass : System.Web.UI.Page
{
private static SqlConnection conn = null;
private static SqlCommand command1 = null;
private static SqlCommand command2 = null;
private static string log = "";
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
try
{
log += "START\n";
string docId = Request.QueryString["docId"];
if (!String.IsNullOrEmpty(docName))
{
bool docExists = doesDocExist(docId);
if (docExists == true)
{
string docMetadata = getMetadata(docId);
Response.Write(docMetadata);
}
}
else
{
// display error message
}
}
catch (sqlException sqlex)
{
// process exception
sendErrorMessage(sqlex.Message);
}
catch (Exception ex)
{
// process exception
sendErrorMessage(ex.Message);
}
}
}
private static bool doesDocExist(string docId)
{
log += "In doesDocExist\n";
bool docExists = false;
try
{
// open db connection (conn)
string cmd = String.Format("SELECT COUNT(*) FROM docs WHERE id='{0}'", docId);
command1 = new SqlCommand(cmd, conn);
conn.Open();
var val = command1.ExecuteScalar();
int numberOfRows = int.Parse(val.ToString());
if (numberOfRows > 0) { docExists = true; }
}
finally
{
// close db connection (conn)
}
return docExists;
}
protected string getMetadata(string docId)
{
log += "In getMetadata\n";
string docMetadata = "";
try
{
// open db connection (conn)
string cmd = String.Format("SELECT metadata FROM docs WHERE id='{0}'", docID);
command2 = new SqlCommand(cmd, conn);
conn.Open();
SqlDataReader rReader = command2.ExecuteReader();
if (rReader.HasRows)
{
while (rReader.Read())
{
// process metadata
docMetadata += DOCMETADATA;
}
}
}
return docMetadata;
}
public static void sendErrorMessage(string messageText)
{
HttpContext.Current.Response.Write(messageText);
// Send string log via email
}
}
}
我知道它太长了,所以这里有一个快速描述。我们有一个使用Page_Load
方法的类和其他三种方法:
从Page_Load
我们致电doesDocExists
。如果返回的值为 true ,则会调用getMetadata
并在屏幕上显示该值。如果有任何错误,则会将其记录在Page_Load
中,并以电子邮件形式发送。
问题在于,如果出现错误,而不是收到包含日志的电子邮件(即:START - 在Function1 - In Function2中),日志会在电子邮件中显示100次(即:START - In Function1 - 在Function2中 - Start - 在Function1中 - 在Function2中 - START ...依此类推),好像Page_Load
多次被触发一样。
由于PostBack,我们在线阅读(http://www.craigwardman.com/blog/index.php/2009/01/asp-net-multiple-page-load-problem/)。所以,我们添加了条件if (!Page.IsPostBack)
,但结果仍然相同。
有多少理由会多次触发Page_Load
?或者是我们对日志变量和/或导致此行为的try / catch做错了吗?
答案 0 :(得分:1)
日志可能很长,因为您将字符串日志声明为 static 。它需要是静态的吗?
答案 1 :(得分:1)
private static SqlConnection conn = null;
private static SqlCommand command1 = null;
private static SqlCommand command2 = null;
private static string log = "";
问题在于日志是 Singleton 以及其他属性。
每当您访问该页面时,都会将文字附加到日志属性,该属性最终为START - In Function1 - In Function2 - Start - In Function1 - In Function2 - START... and so on
根据您的方案,您不需要在myClass中使用 Singleton 。
仅供参考: 由于我不知道您的其余代码,请确保实例化conn, command1, command2
。
答案 2 :(得分:0)
如果您的页面加载功能执行了两次,因为当您点击按钮或链接时可以回发,那么应该检查它并按下面的方式运行
if (!IsPostBack)
{
try
{
log += "START\n";
string docId = Request.QueryString["docId"];
if (!String.IsNullOrEmpty(docName))
{
bool docExists = doesDocExist(docId);
if (docExists == true)
{
string docMetadata = getMetadata(docId);
Response.Write(docMetadata);
}
}
else
{
// display error message
}
}
catch (sqlException sqlex)
{
// process exception
sendErrorMessage(sqlex.Message);
}
catch (Exception ex)
{
// process exception
sendErrorMessage(ex.Message);
}
}
}