游标内的 .Net Core 游标
.Net Core cursor within a cursor
我正忙于开发 .Net Core Web 应用程序,我想知道是否可以在另一个游标内执行一个游标。
我有以下我认为可行的代码
string string = null;
SqlCommand collections_cur = null;
SqlCommand headings_cur = null;
int cl_idno = 0;
sqlserv.Open();
string = " select * from collections " +
" where cl_idno >= @cl_idno ";
collections_cur = new SqlCommand(string, sqlserv);
string = " select * from headings " +
" where hd_cl_idno = @hd_cl_idno ";
headings_cur = new SqlCommand(string, sqlserv);
collections_cur.Parameters.Add(new SqlParameters("cl_idno", 1));
using(SqlDataReader reader1 = collections_cur.ExecuteReader())
{
while(reader1.Read())
{
// some stuff
cl_idno = reader1.GetInt32(0);
headings_cur.Parameters.Add(new SqlParameters("hd_cl_idno", cl_idno));
using(SqlDataReader reader2 = headings_cur.ExecuteReader())
{
while(reader2.Read())
{
// more stuff
}
}
}
}
sqlserv.Close();
上面的程序崩溃了,但出现了以下错误
InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
我认为它会分别处理 reader1 和 reader2,但我不确定如何正确使用第二个 DataReader 对象。
PS
我知道我可以使用
使用单个光标来完成此操作
select * from collections
left join headings on hd_cl_idno = cl_idno
where cl_idno >= 1
但是我使用这个简化的代码是为了让问题更容易阅读。在某些情况下,我需要一个游标内的一个游标,这段代码只是为了说明问题
这似乎是 C# 开发人员不赞成的,但无论如何我都有一个解决方案,如果它可能对任何人都有好处的话。您可能应该自行承担使用它的风险,或者不使用它,但它对我有用。
我对代码做了如下调整
//
// define and initialize variables
//
string credentials = null;
SqlConnection sqlserv = null;
string lv_string = null;
SqlCommand collections_cur = null;
SqlCommand headings_cur = null;
int cl_idno = 0;
//
// connect to database
// MultipleActiveResultSets=True was added
// to allow usage of multiple cursors
//
credentials = "Data Source=(localdb)\MSSQLLocalDB;" +
"Initial Catalog=rescratch;" +
"Integrated Security=True;" +
"Connect Timeout=30;" +
"Encrypt=False;" +
"TrustServerCertificate=True;" +
"ApplicationIntent=ReadWrite;" +
"MultipleActiveResultSets=True;" +
"MultiSubnetFailover=False";
sqlserv = new SqlConnection(credentials);
sqlserv.Open();
//
// declare cursors
//
lv_string = " select * from collections " +
" where cl_idno >= @cl_idno ";
collections_cur = new SqlCommand(lv_string, gv_sqlserv);
collections_cur.Parameters.Add(new SqlParameters("cl_idno", 0));
lv_string = " select * from headings " +
" where hd_cl_idno = @hd_cl_idno ";
headings_cur = new SqlCommand(lv_string, gv_sqlserv);
headings_cur.Parameters.Add(new SqlParameters("hd_cl_idno", 0));
//
// main cursor
//
// set parameter
collections_cur.Parameters["cl_idno"].Value = 1;
using(SqlDataReader lv_reader1 = collections_cur.ExecuteReader())
{
while(lv_reader1.Read())
{
// some stuff
cl_idno = lv_reader1.GetInt32(0);
//
// sub cursor
//
// set parameter
headings_cur.Parameters["hd_cl_idno"].Value = cl_idno;
using(SqlDataReader lv_reader2 = headings_cur.ExecuteReader())
{
while(lv_reader2.Read())
{
// more stuff
}
}
}
}
sqlserv.Close();
我正忙于开发 .Net Core Web 应用程序,我想知道是否可以在另一个游标内执行一个游标。
我有以下我认为可行的代码
string string = null;
SqlCommand collections_cur = null;
SqlCommand headings_cur = null;
int cl_idno = 0;
sqlserv.Open();
string = " select * from collections " +
" where cl_idno >= @cl_idno ";
collections_cur = new SqlCommand(string, sqlserv);
string = " select * from headings " +
" where hd_cl_idno = @hd_cl_idno ";
headings_cur = new SqlCommand(string, sqlserv);
collections_cur.Parameters.Add(new SqlParameters("cl_idno", 1));
using(SqlDataReader reader1 = collections_cur.ExecuteReader())
{
while(reader1.Read())
{
// some stuff
cl_idno = reader1.GetInt32(0);
headings_cur.Parameters.Add(new SqlParameters("hd_cl_idno", cl_idno));
using(SqlDataReader reader2 = headings_cur.ExecuteReader())
{
while(reader2.Read())
{
// more stuff
}
}
}
}
sqlserv.Close();
上面的程序崩溃了,但出现了以下错误
InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
我认为它会分别处理 reader1 和 reader2,但我不确定如何正确使用第二个 DataReader 对象。
PS
我知道我可以使用
使用单个光标来完成此操作select * from collections
left join headings on hd_cl_idno = cl_idno
where cl_idno >= 1
但是我使用这个简化的代码是为了让问题更容易阅读。在某些情况下,我需要一个游标内的一个游标,这段代码只是为了说明问题
这似乎是 C# 开发人员不赞成的,但无论如何我都有一个解决方案,如果它可能对任何人都有好处的话。您可能应该自行承担使用它的风险,或者不使用它,但它对我有用。
我对代码做了如下调整
//
// define and initialize variables
//
string credentials = null;
SqlConnection sqlserv = null;
string lv_string = null;
SqlCommand collections_cur = null;
SqlCommand headings_cur = null;
int cl_idno = 0;
//
// connect to database
// MultipleActiveResultSets=True was added
// to allow usage of multiple cursors
//
credentials = "Data Source=(localdb)\MSSQLLocalDB;" +
"Initial Catalog=rescratch;" +
"Integrated Security=True;" +
"Connect Timeout=30;" +
"Encrypt=False;" +
"TrustServerCertificate=True;" +
"ApplicationIntent=ReadWrite;" +
"MultipleActiveResultSets=True;" +
"MultiSubnetFailover=False";
sqlserv = new SqlConnection(credentials);
sqlserv.Open();
//
// declare cursors
//
lv_string = " select * from collections " +
" where cl_idno >= @cl_idno ";
collections_cur = new SqlCommand(lv_string, gv_sqlserv);
collections_cur.Parameters.Add(new SqlParameters("cl_idno", 0));
lv_string = " select * from headings " +
" where hd_cl_idno = @hd_cl_idno ";
headings_cur = new SqlCommand(lv_string, gv_sqlserv);
headings_cur.Parameters.Add(new SqlParameters("hd_cl_idno", 0));
//
// main cursor
//
// set parameter
collections_cur.Parameters["cl_idno"].Value = 1;
using(SqlDataReader lv_reader1 = collections_cur.ExecuteReader())
{
while(lv_reader1.Read())
{
// some stuff
cl_idno = lv_reader1.GetInt32(0);
//
// sub cursor
//
// set parameter
headings_cur.Parameters["hd_cl_idno"].Value = cl_idno;
using(SqlDataReader lv_reader2 = headings_cur.ExecuteReader())
{
while(lv_reader2.Read())
{
// more stuff
}
}
}
}
sqlserv.Close();