我有以下代码:
SqlConnection connection1, connection2;
SqlCommand command1, command2;
SqlDataReader reader1, reader2;
using (connection1 = new SqlConnection("connection string here"))
{
using (command1 = new SqlCommand(@"SELECT * FROM [SERVER1].[DATABASE1].[TABLE1] WHERE COL1 = @COL1 AND COL2 = @COL2", connection1))
{
command1.Parameters.Add("@COL1", SqlDbType.VarChar, 255).Value = TextBox1.Text;
command1.Parameters.Add("@COL2", SqlDbType.VarChar, 255).Value = TextBox2.Text;
connection1.Open();
using (reader1 = command1.ExecuteReader())
{
while (reader1.Read())
{
int COL3Index = reader1.GetOrdinal("COL3");
Console.Write("### LOOP 1 ###");
Console.Write(reader1.GetDouble(COL3Index));
using (connection2 = new SqlConnection("same connection string here"))
{
using (command2 = new SqlCommand(@"SELECT * FROM [SERVER1].[DATABASE1].[TABLE2] WHERE COL1 = @COL1", connection1))
{
command2.Parameters.Add("@COL1", SqlDbType.Float).Value = reader1.GetDouble(COL3Index);
connection2.Open();
using (reader2 = command2.ExecuteReader())
{
while (reader2.Read())
{
int COL2Index = reader2.GetOrdinal("COL2");
Console.Write("### LOOP 2 ###");
Console.Write(reader2.GetDouble(COL2Index));
}
}
}
}
}
}
}
}
基本上,我将需要这样做5次,即循环内循环内循环内循环内循环…
第一个循环自己工作,但第二个循环不起作用,并给出以下错误:
已经有一个与这个命令相关联的打开的数据读取器必须先关闭
on line:
using (reader2 = command2.ExecuteReader())
当我需要嵌入循环
这是Select N+1的定义,应该尽可能避免。我建议使用实体框架之类的东西,并急切地加载子值。
如果不可能避免,循环遍历整个reader1结果,赋值给一个本地集合,关闭reader1,然后遍历本地集合并基于本地值加载
如果对相同的数据库/连接字符串启用了MARS,则没有理由打开两次连接。这可以通过将"MultipleActiveResultSets=True"
添加到连接字符串来实现。
此外,您可以使用DataAdapter将数据加载到DataSet/DataTable中,然后查询DataSet。但是,这假设您的表不是太大,您可以将它们加载到内存中,否则ORM将是更好的选择。
一个ORM解决方案,如LINQ-to-SQL或LINQ-to-Entities通过实体框架(如在Mike Cole的回答中提到的)可以真正帮助你在这里,所以你不需要担心编写这些查询和处理连接。相反,您只需依赖于DataContext来处理连接。