简体   繁体   中英

SQL Nested Queries in C# and Connection Open Problem

I have three tables and my requirement is to fetch their records by using the parent record of each table.

So I have three queries. Here is a code sample:

First Query

SQLConnection con = new SQLConnection("connectionstring");

SQLCommand cmd1 = new SQLCommand (1stQuery,con);
SQLDataReader rs1 = cmd1.DataReader();

while (rs1.Read()) {

// Making 2nd Query, 2nd Query is using 1st Query result

SQLCommand cmd2 = new SQLCommand(2ndQuery,con);
SQLDataReader rs2 = cmd2.DataReader();

while (rs2.Read()){

//Making 3rd Query using 2nd Query result
}
}

It gives the error that there is already an open DataReader. I dont want to close the SQL connection and open it for each query, as this is bad for performance.

I want to use only one SQL Connection for all the queries.

You don't need to close the connection. The problem (as the error suggests) is that you're not closing one DataReader before starting the next.

As Oded says, you have a "select N+1" problem, but let's disregard that for the sake of this answer.

The easiest thing to do is read the entire first dataset into memory before you start reading the next one:

var list1 = new List<Foo>();
using (var rdr1 = cmd1.ExecuteReader())
{
    list1.Add(...);
}

var list2 = new List<Bar>();
var cmd2 = ...;
foreach (var item in list1)
{
    // assign parameters to cmd2 from item

    using (var rdr2 = cmd2.ExecuteReader())
    {
        list2.Add(...);
    }
}

... and so on.

The other option is to enable MARS on your connection, which lets you have multiple DataReaders active simultaneously. This is almost always a bad idea so let's pretend I never suggested it.

If you are nesting calls to the database, you will need to use different connections.

You have a worse problem here with a call to the DB in a loop - also known as the N+1 problem .

I suggest rewriting your database and application logic - use a join in the database to consolidate the separate queries into one and change the logic to use the result.

I suggest to use ExecuteDataSet . It will contain the result of all three queries. Moveover, These queries should be executed in stored procedure.

Otherwise you are inviting Sql Injections

Sql Injections

Set MultipleActiveResultsets property of your connection string to true, but the performance of your code is poor. Try wrapping your queries in a stored procedure to avoid loops.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM