执行存储过程的C#函数和SqlCommand出现问题
本文关键字:SqlCommand 问题 函数 存储过程 执行 | 更新日期: 2023-09-27 18:24:13
这是我在这里的第一篇文章。我真的很喜欢这个地方,到目前为止我发现了很多有趣的东西,所以我决定登机!
我在C#中尝试使用递归调用时遇到了一些奇怪的事情。这就是我正在做的。
//routine for downloading Phases
public static int DownloadPhases(string competitionId, string competitionCountry, string competitionPhase = "")
{
DataTable dt = new DataTable();
DateTime phaseStart = DateTime.Now, phaseEnd = DateTime.Now, outDate;
XmlDocument xmlDoc = new XmlDocument();
bool isDate = false, isNumeric = false;
string url = "", phaseId = "", phaseCode = "", phaseName = "", phaseDesc = "";
int phaseSort = 0, outNum = 0, result = 0;
// load structure for inserting new Phases
SqlUtilities.sqlLoadDt(ConfigurationManager.AppSettings["sqlSel_insCompetitionsPhase"], ref dt);
DataColumn[] keyColumn2 = new DataColumn[3];
keyColumn2[0] = dt.Columns["phase_ID"];
keyColumn2[1] = dt.Columns["phase_Competition"];
keyColumn2[2] = dt.Columns["phase_Country"];
dt.PrimaryKey = keyColumn2;
try
{
if (competitionPhase == "")
url = buildUrl("15", "", "", competitionCountry, competitionId);
else
url = buildUrl("15", "", "", competitionCountry, competitionPhase);
loadXml(xmlDoc, url);
// set a nodelist with all the <category> tags for Phases
XmlNodeList competitions = xmlDoc.GetElementsByTagName("Item");
// for each node in the the nodelist, get all the infos about it
foreach (XmlNode competition in competitions)
{
//phase
phaseId = competition.Attributes.GetNamedItem("id").Value.ToString();
phaseCode = competition.Attributes.GetNamedItem("code").Value.ToString();
phaseName = competition.Attributes.GetNamedItem("name").Value.ToString();
phaseDesc = competition.Attributes.GetNamedItem("description").Value.ToString();
isDate = DateTime.TryParse(competition.Attributes.GetNamedItem("comp_start").Value.ToString(), out outDate);
if (isDate == true)
phaseStart = outDate;
isDate = DateTime.TryParse(competition.Attributes.GetNamedItem("comp_end").Value.ToString(), out outDate);
if (isDate == true)
phaseEnd = outDate;
isNumeric = int.TryParse(competition.Attributes.GetNamedItem("sort").Value.ToString(), out outNum);
if (isNumeric == true)
phaseSort = outNum;
// adding competition to datatable dt
if (phaseId != "")
{
try
{
dt.Rows.Add(phaseId, competitionId, competitionCountry, phaseCode, phaseStart, phaseEnd, phaseDesc, phaseName, phaseSort);
result += 1;
if (phaseDesc.Contains("NOT LEAF"))
<b>DlData.DownloadPhases(competitionId, competitionCountry, phaseId);</b>
}
catch (Exception ex)
{
ex.Message.ToString();
}
finally
{
phaseId = "";
}
}
} //end foreach phase
}
catch (Exception ex)
{
ex.Message.ToString();
}
finally
{
//call stored procedure to insert Phases
SqlUtilities.sqlExecuteSp("dbo.usp_insCompetitionsPhase", dt);
}
return result;
}
这就是SqlExecuteSp
函数
public static void sqlExecuteSp(string cmdText, DataTable parDt)
{
try
{
SqlConnection conn = new SqlConnection();
SqlCommand comm = new SqlCommand();
SqlParameter param = new SqlParameter();
SqlTransaction trans;
conn.ConnectionString = ConfigurationManager.ConnectionStrings["FTBLConnectionStringSuperUser"].ConnectionString;
conn.Open();
using (conn)
{
trans = conn.BeginTransaction();
comm.CommandText = cmdText;
comm.Connection = conn;
comm.CommandType = CommandType.StoredProcedure;
comm.Transaction = trans;
param = comm.Parameters.AddWithValue("@dt", parDt);
param.SqlDbType = SqlDbType.Structured;
comm.ExecuteNonQuery();
trans.Commit();
}
conn.Close();
}
catch (Exception ex)
{
ex.Message.ToString();
}
}
当我尝试递归调用SqlExecuteSp
函数时,它似乎正确地执行了它,但直到删除第一行时,我才能看到插入的新行。
因此,如果我在SQLServerManagementStudio中运行delete from tbl_competition_phases
,它只删除"旧"行,从现在起,我可以看到第二次调用插入的行。
我认为这是由于一个不完整的事务导致的,所以,正如您所看到的,我添加了一个事务对象,但没有结果。
我知道c#中的递归调用不是最好的方法。无论如何,在这种情况下,我很确定不会有超过2个调用,所以我认为这不会是一个问题。
有什么建议吗?
非常感谢!
Damiano
我想我已经发现了可能的错误——在sqlExecuteSp方法中,您的conn位于using块中(声明错误)——但在它被处理后,正在调用它之外的close。这将导致异常。正如我在评论中所说,你吞下例外的事实是在向你隐瞒这一点。
请对sqlExecuteSp方法尝试此操作
public static void sqlExecuteSp(string cmdText, DataTable parDt)
{
using (SqlConnection conn = new SqlConnection())
{
using (SqlCommand comm = new SqlCommand())
{
conn.ConnectionString = ConfigurationManager.ConnectionStrings["FTBLConnectionStringSuperUser"].ConnectionString;
conn.Open();
using (SqlTransaction trans = conn.BeginTransaction())
{
comm.Connection = conn;
comm.CommandType = CommandType.StoredProcedure;
comm.Transaction = trans;
SqlParameter param = comm.Parameters.AddWithValue("@dt", parDt);
param.SqlDbType = SqlDbType.Structured;
comm.ExecuteNonQuery();
trans.Commit();
}
}
conn.Close();
}
}
这可能不是您所看到的行为的原因,但在程序运行时肯定会导致错误/意外行为。
的一些提示
- 封闭可以在使用块中处理的对象,以确保它们即使发生错误(例如,如果您的连接字符串配置文件中缺少),并使用我的示例中所示的正确方法
- 减少变量的范围(只在需要时声明它们)-减少了它们必须存在的时间,并使代码更具可读性(例如,我将SqlParameter声明下移到只需要的位置)
- 最后不要麻烦使用try-catch,除非它是更广泛的异常处理框架的一部分——或者只有当你想记录异常,并且你正在重新记录,这样错误就会冒出来。通过在不需要的地方使用它,你可以隐藏错误,这些错误本可以帮助你诊断问题。有时,单独使用try/finally来确保运行一些代码是值得的——请注意,您不必使用catch块。这个问题有一些有用的解读