一段时间内使用foreach循环的奇怪行为READ()

时间:2011-08-29 08:08:15

标签: c# sql sql-server

我是VFP开发人员,试图拿起C#。确定最快的学习方法是做,我为自己做了一个小练习。

目标

将某些事务从“实时”数据库移动到存档数据库中。

一般的想法是:

  • 获取“合适”作业(父级)的列表,然后逐个阅读() 之一。
  • 使用foreach循环处理子表列表,插入 历史数据库中的新记录,然后删除旧记录 来自“现场”表。
  • 将实际作业(父级)移至归档,然后将其从“live”
  • 中删除

一开始就没事了,然后我突然碰到了一堵砖墙......

问题

我有一个名为RefCombo的变量,我用它来存储父键的主键,它存储在while (READ())语句之后和foreach循环之前。

在四个记录的测试数据库中,RefCombo字段应为:

read()结果:Job1

预先列出的预定列表中的子表格

  • 处理ChildTable1

  • 处理ChildTable2

  • 处理ChildTable3

  • 处理ChildTable4

  • 处理ChildTable5

然后重复Job2,Job3和Job4。

让我疯狂的是我得到了这个:

read()结果:Job1

预先列出的预定列表中的子表格

  • 处理ChildTable1

  • SKIP其他ChildTables,RefCombo(主键)成为Job2,循环回while read()

问题是,一旦它改变为Job2,它就会像我预期的那样继续工作,为每个剩余的父记录循环遍历每个子表。

我也得到了“当前的TransactionScope已经完成”。每隔一次我运行网页时出错。这发生在程序开始时的connection.open()部分,但很难确定,因为它不会一直发生。

我已经将代码发布在底部,它的排序很随意,但是任何帮助都会非常感激。我已经在这个工作了2天,真的买不起脱发,哈哈。

对我的代码的任何评论也会更受欢迎,我真的是C#的新手并且每一点都有帮助:P

提前致谢。

#region Declaration
DateTime FromDate = Convert.ToDateTime("01/01/2011");
DateTime ToDate = Convert.ToDateTime("01/03/2011");
string conStrSource = @"Data Source=HOME\SQLEXPRESS;Initial Catalog=MCC_Live;Integrated Security=True";

// Declare a list of child tables to check and move together with the Job
List<String> TablesToMove = new List<String>();
    {
    TablesToMove.Add("JobItems");
    TablesToMove.Add("JobTerms");
    TablesToMove.Add("JobMessages");
    TablesToMove.Add("JobCalcs");
    TablesToMove.Add("JobContainers");
    TablesToMove.Add("JobMetrics");
    }
#endregion

#region Set SQL String
string QueryString =
    "SELECT " +
    "JobMaster.BranchID, JobMaster.JobNo, " +
    "JobMaster.ImportDate, PermitStatus.CurrentStatus " +
    "FROM JobMaster. " +
    "INNER JOIN PermitStatus ON " +
        "JobMaster.BranchID = PermitStatus.BranchID AND " +
        "JobMaster.JobNo = PermitStatus.JobNo " +
    "WHERE " +
        "(JobMaster.ImportDate BETWEEN @FromDate AND @ToDate) AND " +
        "PermitStatus.currentStatus NOT IN ('HT0', 'HT1', 'HT2')";
#endregion

// Display on web page for reference
ASPxFromDate.Value = FromDate;
ASPxToDate.Value = ToDate;
ASPxMemo1.Value = QueryString;

#region Open Connection, Get List of filtered Master Jobs
using (SqlConnection connection = new SqlConnection(conStrSource))
    {
        int JobCount = 0;
        ASPxListBox1.Items.Clear();
        ASPxListBox2.Items.Clear();
        ASPxListBox3.Items.Clear();
        ASPxListBox1.Columns.Clear(); 

        SqlCommand command = new SqlCommand(QueryString, connection);
            {
            command.Parameters.Add(new SqlParameter("@FromDate", FromDate));
            command.Parameters.Add(new SqlParameter("@ToDate", ToDate));
            }
        connection.Open();
        SqlDataReader FilteredJobList = command.ExecuteReader();

#endregion

        try // Process MasterJob File
        {
        // Process individual jobs one by one so I won't tie up memory and have better logging
        while (FilteredJobList.Read())
            {
            #region Declare variables
            string RefCombo = (string)FilteredJobList[0] + (string)FilteredJobList[1]; //Get primary key
            JobCount = JobCount + 1;
            ASPxTextBox2.Value = JobCount;
            ASPxListBox2.Items.Add(RefCombo);
            #endregion

            // Start transaction scope
            TransactionScope TranScope = new TransactionScope();
                {
                try
                    {
                    // Loop through child tables
                    foreach (string CurrentTable in TablesToMove)
                        {
                        #region Transfer child tables
                        // update list so I know which part its working on
                        ASPxListBox1.Items.Add(CurrentTable);  
                        RefCombo = (string)FilteredJobList[0] + (string)FilteredJobList[1];
                        string RefTableNow = (string)CurrentTable;
                        bool CancelTrans = false;
                        MoveChild(ref RefCombo, ref RefTableNow, ref conStrSource, ref CancelTrans);
                            if (CancelTrans == false)
                                { //LogFailure();
                                break;
                                }
                        DelChild(ref RefCombo, ref RefTableNow, ref conStrSource, ref CancelTrans);
                            if (CancelTrans == false)
                                { //LogFailure();
                                break;
                                }
                        #endregion
                            // Remove remaing entries
                            //MoveLatestStatus();
                            //DeleteLatestStatus();
                            //MoveMasterJob();
                            //DeleteMasterJob();
                            //LogSuccess();
                            TranScope.Complete();
                        }
                catch
                    {
                    //LogFailure();
                    }
                }
            }
        finally
            {
                FilteredJobList.Close();
            }
        }
    }


//------------------------------------------------------------------------------------------------

private void MoveChild(ref string RefCombo, ref string CurrentTable, ref string conStrSource, ref bool CancelTrans)
    {
    #region Define Insert String
    string InsertSqlString =
        "INSERT INTO [MCC_History].[dbo].[" + @CurrentTable + "]" +
        " SELECT * FROM [MCC_Live].[dbo].[" + @CurrentTable + "] s" +
        " WHERE NOT EXISTS" +
        " (SELECT 1 FROM [MCC_History].[dbo].[" + @CurrentTable + "] t2" +
        " WHERE t2.BranchID + t2.JobNo = s.BranchID + s.JobNo)" +
        " AND s.BranchID + s.JobNo = @RefCombo";

    #endregion

    #region Open connection and execute query
    using (SqlConnection MoveConnect = new SqlConnection(conStrSource))
        {
        try
            {
            SqlCommand InsertCommand = new SqlCommand(InsertSqlString, MoveConnect);
                {
                InsertCommand.Parameters.Add(new SqlParameter("@RefCombo", RefCombo));
                }
            MoveConnect.Open();
            InsertCommand.ExecuteNonQuery();
            }
        catch
            {
            CancelTrans = true;
            }
        }
    #endregion
    }

//------------------------------------------------------------------------------------------------

private void DeleteChild(ref string RefCombo, ref string CurrentTable, ref string conStrSource, ref bool CancelTrans)
    {
    #region Define Delete query
    string DeleteSqlString =
        " DELETE FROM [MCC_Live].[dbo].[" + @CurrentTable + "]" +
        " WHERE [MCC_Live].[dbo].[" + @CurrentTable + 
        "].BranchID + [MCC_DB].[dbo].[" + @CurrentTable + "].JobNo = @RefCombo";
    #endregion

    #region Execute Delete query
    using (SqlConnection MoveConnect = new SqlConnection(conStrSource))
        {
        try
            {
            SqlCommand InsertCommand = new SqlCommand(DeleteSqlString, MoveConnect);
                {
                InsertCommand.Parameters.Add(new SqlParameter("@RefCombo", RefCombo));
                }
            MoveConnect.Open();
            InsertCommand.ExecuteNonQuery();
            }
        catch
            {
            CancelTrans = true;
            }
        }
    #endregion
    }

1 个答案:

答案 0 :(得分:0)

问题在于您拥有TranScope.Complete();声明。它在你的foreach循环内部,它在你的Foreach块退出后属于它。您在列表的第一次迭代结束时完成交易。这可以防止您通过此事务再发出任何命令。