【问题标题】:How to "reset" C# SqlCommand object so I can re-use it in a loop如何“重置” C# SqlCommand 对象,以便我可以在循环中重新使用它
【发布时间】:2015-08-17 16:45:27
【问题描述】:

我在 foreach 循环中有这段代码,它为每个文件夹调用一个 sql 函数

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
}                

工作正常,但是有很多重复的代码,这可能是不必要的。

是否可以在循环之外创建 SqlCommand 对象并仅“重置”循环中的参数值?我怎样才能重用该对象? (请非常具体)。

或者我应该继续在循环中包含这段代码,每次迭代都会使用不同的数据执行 fn 3 次?当每次几乎完全相同时,继续重新创建 SqlCommand 对象似乎效率低下。

【问题讨论】:

  • 您从列表中弹出的每个项目最多调用 fnChkXfer 3 次,基本上区别在于@FileType 的值?如果没有理由继续检查文件,似乎你可以有一个内部 for 循环并跳出循环。
  • 也就是说,在做什么?根据名称,您似乎拥有所有子文件夹的列表,并且基于此 tsql 函数调用,您正在执行一些操作系统级别的活动(假设复制文件)。感觉不是很……SSIS-ey。我怀疑我们可以使用更多开箱即用的组件,如果您可以帮助我们了解您要解决的问题,这可能会产生更易于维护且缺陷更少的软件包
  • 是的,没错。我调用该函数 3 次,区别在于文件类型。我必须确定文件夹中的文件是否已针对每种类型传输,然后使用 WinSCP 传输文件(从源上的 3 个位置到目标上的 2 个差异位置)。我不能使用 SyncFiles 中内置的 WinSCP,因为 2 个系统上的文件结构不同,而且我没有重写工作代码来简化此传输(目前是手动完成的)。我通过此转移来结束现有的 SSIS 包。我正在解决的问题是自动化 SFTP 传输。
  • 完美!有时人们在使用 SSIS 时会使用熟悉的 (.net),而没有探索本机任务,这会导致不太好的体验。听起来你有一个很好的理由走这条路,但如果我另有暗示,我深表歉意
  • 我无法摆脱检查任何东西。我必须检查每个文件夹的所有 3 种类型。我更喜欢使用 WinSCP 的更多“开箱即用”功能,但文件夹结构禁止这样做。我更希望能够在从源传输之前检查目标上的实际文件,但没有 WinSCP 命令可以在两端执行此操作。

标签: c# foreach ssis sqlcommand


【解决方案1】:

我将您的列表更改为字典以添加文件类型。如果要重用相同的 sqlcommand 对象,则需要在每次循环迭代中执行它。所以我添加了那部分。您可能想添加一个尝试,也可以在那里捕获。

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
      }
}

在这段代码中,对象是在循环之外完整创建的,foreach 中唯一的更改是对对象参数的值进行的。

另一方面,我不太确定您使用 FileXferred 返回参数做了什么。你在什么地方用过吗?

更新

这是每个目录都将所有文件类型应用于目录的代码。

        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
                }
            }
        }

【讨论】:

  • @Billinkc,你是对的。它需要更新以反映这一点。但是可重用的单个sqlcommand对象的想法就在这里。
  • 感谢您的建议。我喜欢第二个版本,并且会以这种方式实现。
【解决方案2】:

您绝对可以(甚至应该)在循环之外创建SqlCommand,并随着循环的进行不断更改参数。为此,您需要在添加参数时存储参数,然后在循环中设置它们的值。您还应该在完成命令后关闭它们,最好以某种自动化方式。 using 语句是最常见的选择。

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

【讨论】:

  • 你在这里创建了三个 sqlcommand,而不是一个可重用的。
猜你喜欢
  • 1970-01-01
  • 2015-06-21
  • 2015-08-30
  • 1970-01-01
  • 2010-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多