简体   繁体   中英

How to “reset” C# SqlCommand object so I can re-use it in a loop

I have this code in a foreach loop that calls a sql function for each folder

foreach (string strCurrentFolder in strLocalSubFolderList)
{          
    SqlCommand sqlComm1 = new SqlCommand("dbo.fnChkXfer", _sqlConn);
    sqlComm1.CommandType = CommandType.StoredProcedure;
    sqlComm1.Parameters.Add("@FileXferred",SqlDbType.Bit).Direction = ParameterDirection.ReturnValue;
    sqlComm1.Parameters.AddWithValue("@UNCFolderPath", strCurrentFolder);
    sqlComm1.Parameters.AddWithValue("@FileType", "Type 1");
    ...if files not transferred, then transfer them

    SqlCommand sqlComm2 = new SqlCommand("dbo.fnChkXfer", _sqlConn);
    sqlComm2.CommandType = CommandType.StoredProcedure;
    sqlComm2.Parameters.Add("@FileXferred",SqlDbType.Bit).Direction = ParameterDirection.ReturnValue;
    sqlComm2.Parameters.AddWithValue("@UNCFolderPath", strCurrentFolder);
    sqlComm2.Parameters.AddWithValue("@FileType", "Type 2");
    ...if files not transferred, then transfer them

    SqlCommand sqlComm3 = new SqlCommand("dbo.fnChkXfer", _sqlConn);
    sqlComm3.CommandType = CommandType.StoredProcedure;
    sqlComm3.Parameters.Add("@FileXferred",SqlDbType.Bit).Direction = ParameterDirection.ReturnValue;
    sqlComm3.Parameters.AddWithValue("@UNCFolderPath", strCurrentFolder);
    sqlComm3.Parameters.AddWithValue("@FileType", "Type 3");
    ...if files not transferred, then transfer the
}                

It works fine, but there is a lot of duplicated code, which may be unnecessary.

Is it possible to create the SqlCommand object once outside of the loop and "reset" just the parameter values in the loop? How could I reuse the object? (Please be very specific).

Or should I continue to include this block of code in the loop, which executes the fn 3 times with different data for each iteration? It seems inefficient to keep recreating the SqlCommand object when it's almost exactly the same every time.

I changed your list to dictionary to add the Filetype. If you're going to reuse the same sqlcommand object, you need to execute it in every loop iteration. So I added that part. You may want to add a try, catch in there too.

Dictionary<string,string> strLocalSubFolderDict = new Dictionary<string, string>();

strLocalSubFolderDict.Add( "Type 1", "Directory 1");
strLocalSubFolderDict.Add( "Type 2", "Directory 2");
strLocalSubFolderDict.Add( "Type 3", "Directory 3");

using (SqlCommand sqlComm = new SqlCommand("dbo.fnChkXfer", _sqlConn))
{
     sqlComm.CommandType = CommandType.StoredProcedure;
     sqlComm.Parameters.Add("@FileXferred", SqlDbType.Bit).Direction = ParameterDirection.ReturnValue;
     sqlComm.Parameters.Add("@UNCFolderPath");
     sqlComm.Parameters.Add("@FileType");

     foreach (var val in strLocalSubFolderDict)
     {
         sqlComm.Parameters["@UNCFolderPath"].Value = val.Value;
         sqlComm.Parameters["@FileType"].Value = val.Key;
         sqlComm.ExecuteNonQuery();
         //    ...if files not transferred, then transfer them
      }
}

In this code the object is complete created outside the loop and the only changes in foreach are done to the values on the parameters of the object.

On a side, I'm not quite sure what you're doing with the FileXferred return parameter. Do you use it somewhere?

Update

Here's the code with where every directory has all the FileTypes applied to the directory.

        List<string> strLocalSubFolderList = new List<string>();
        List<string> typesList = new List<string>();

        typesList.Add("Type 1");
        typesList.Add("Type 2");
        typesList.Add("Type 3");

        using (SqlCommand sqlComm = new SqlCommand("dbo.fnChkXfer", _sqlConn))
        {
            sqlComm.CommandType = CommandType.StoredProcedure;
            sqlComm.Parameters.Add("@FileXferred", SqlDbType.Bit).Direction = ParameterDirection.ReturnValue;
            sqlComm.Parameters.Add("@UNCFolderPath");
            sqlComm.Parameters.Add("@FileType");

            foreach (var directval in strLocalSubFolderList)
            {
                foreach ( var typeval in typesList)
                {
                    sqlComm.Parameters["@UNCFolderPath"].Value = directval;
                    sqlComm.Parameters["@FileType"].Value = typeval;
                    sqlComm.ExecuteNonQuery();
                    //    ...if files not transferred, then transfer them
                }
            }
        }

You definitely can (and even should) create your SqlCommand outside the loop, and keep changing parameters as the loop progresses. In order to do that you need to store your parameters as you add them, and then set their values in the loop. You should also close the commands when you are done with them, preferably in some automated way. using statement is the most common choice for that.

using (var cmd = new SqlCommand("dbo.fnChkXfer", _sqlConn)) {
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add("@FileXferred",SqlDbType.Bit).Direction = ParameterDirection.ReturnValue;
    var p2 = cmd.Parameters.AddWithValue("@UNCFolderPath", DbType.Varchar, 32); // << Set the correct size
    var typeParam = cmd.Parameters.AddWithValue("@FileType", , DbType.Varchar, 32);
    foreach (string strCurrentFolder in strLocalSubFolderList) {
        p2.Value = strCurrentFolder;
        foreach (var typeVal in new[] {"Type 1", "Type 2", ...}) {
            typeParam.Value = typeVal;

            ... // Set values of the remaining parameters
            ... // Use your command as needed
        }
    }
}
// After this point all three commands will be closed automatically

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