使用 Foreach 循环的问题

Posted

技术标签:

【中文标题】使用 Foreach 循环的问题【英文标题】:Issues Using Foreach Loop 【发布时间】:2021-01-24 19:37:30 【问题描述】:

我正在尝试使用 Foreach 循环来计算在我的申请中发放贷款的人支付的利息。应用程序加载所有已发放贷款的列表,贷款账户余额小于零的将被借记还款。如果该人只收到一次贷款,但如果他收到两次或三次,则贷款在所有三个实例中都使用相同的旧余额。

下面是代码:

DateTime WATTime = Timezones.WATTimezone();  //Calling the Timezone method from class to use the West Central Africa Timezone 

        var date = DateTime.Today;
        var zone = TimeZoneInfo.FindSystemTimeZoneById("W. Central Africa Standard Time");

        // var presentDates = date.Date;  // das;
        DateTime currentTime = TimeZoneInfo.ConvertTime(date, zone);

        var loanDates = currentTime.Date;
        var loanDate = loanDates.ToShortDateString();


        List<LoanProcessed> loanProcessed = (from l in db.LoanProcesseds
                                             where l.first_Repayment_Date.Equals(loanDate)
                                             || l.second_Repayment_Date.Equals(loanDate)
                                             || l.third_Repayment_Date.Equals(loanDate)
                                             || l.fourth_Repayment_Date.Equals(loanDate)
                                             || l.fifth_Repayment_Date.Equals(loanDate)
                                             || l.sixth_Repayment_Date.Equals(loanDate)
                                             || l.seventh_Repayment_Date.Equals(loanDate)
                                             || l.eighth_Repayment_Date.Equals(loanDate)
                                             || l.Ninth_Repayment_Date.Equals(loanDate)
                                             || l.Tenth_Repayment_Date.Equals(loanDate)
                                             || l.Eleventh_Repayment_Date.Equals(loanDate)
                                             || l.Twelfth_Repayment_Date.Equals(loanDate)

                                             select l
                                             ).ToList();


        foreach (var item in loanProcessed)
        

            var loan_Accountdetails = db.LoanAccounts.Where(c => c.Account_Number == item.Account_Number).FirstOrDefault();
            var loan_AccountBalance = db.LoanAccounts.Where(a => a.Account_Number == loan_Accountdetails.Account_Number).FirstOrDefault().Account_Balance;

            // Handling First Repayment
            var firstRepay = item.first_Repayment_Date;
            if (loan_AccountBalance < 0)
            
                //continue;
                if (firstRepay != "Nill" && firstRepay != "")
                

                    if (DateTime.ParseExact(firstRepay, "dd/MM/yyyy", CultureInfo.InvariantCulture).Date == WATTime.Date)
                    
                        // Credit the Loan Account with the Monthly Repayment
                        try
                        

                            var principalRepayment = item.Monthly_Repayment;

                            // Retrieve Current Account Balance First

                            var old_LoanBalance = db.LoanAccounts.Where(a => a.Account_Number == loan_Accountdetails.Account_Number).FirstOrDefault().Account_Balance;
                            var new_LoanBalance = old_LoanBalance + principalRepayment;
                            // Update the LoanAccount Balance First
                            using (var db1 = new CreditFacilityContext())
                            
                                var result = db1.LoanAccounts.SingleOrDefault(b => b.Account_Number == item.Account_Number);
                                if (result != null)
                                
                                    result.Account_Balance = new_LoanBalance;
                                    db1.SaveChanges();
                                
                            

// Debit the Current Account with the Monthly Repayment
                        try
                        
                            var currentAccountDetails = db.CurrentAccounts.Where(b => b.Account_Number == loan_Accountdetails.Current_AccountNumber).FirstOrDefault();

                            var principalRepayment = item.Monthly_Repayment;
                            var old_CurrentAccountBalance = db.CurrentAccounts.Where(a => a.Account_Number == loan_Accountdetails.Current_AccountNumber).FirstOrDefault().Account_Balance;
                            var new_CurrentAccountBalance = old_CurrentAccountBalance - principalRepayment;
                            // Update the CurrentAccount Balance First
                            string connString = ConfigurationManager.ConnectionStrings["CreditFacilityContext"].ConnectionString;
                            SqlTransaction transaction1;
                            using (SqlConnection connection = new SqlConnection(connString))
                            
                                using (SqlCommand command = new SqlCommand())
                                
                                    connection.Open();
                                    command.Connection = connection;
                                    transaction1 = connection.BeginTransaction(IsolationLevel.Serializable);
                                    command.CommandType = CommandType.Text;
                                    command.Transaction = transaction1;
                                    command.CommandText = "UPDATE CurrentAccounts SET Account_Balance=@Account_Balance WHERE (Account_Number=@Account_Number)";
                                    command.Parameters.Add("@Account_Balance", SqlDbType.Decimal).Value = new_CurrentAccountBalance;
                                    command.Parameters.Add("@Account_Number", SqlDbType.NVarChar).Value = loan_Accountdetails.Current_AccountNumber;

                                    try
                                    

                                        transaction1.Commit();
                                        int recordsAffected = command.ExecuteNonQuery();

                                    
                                    catch (SqlException d)
                                    
                                        Console.Write(d.Message, "Error in Saving");
                                    
                                    finally
                                    
                                        connection.Close();
                                    

                                

                            

                    
                
            

如果一个帐号在 loanprocessed 中出现一次,它可以正常工作,但如果它出现两次,它将使用相同的 old_loanBalance 用于所有出现,有一个更新 LoanAccount 的代码但如果它不止一个,它似乎不起作用。

// Update the LoanAccount Balance First
                        using (var db1 = new CreditFacilityContext())
                        
                            var result = db1.LoanAccounts.SingleOrDefault(b => b.Account_Number == item.Account_Number);
                            if (result != null)
                            
                                result.Account_Balance = new_LoanBalance;
                                db1.SaveChanges();
                            
                        

【问题讨论】:

【参考方案1】:

您正在使用相同的 DbContext 实例来获取 old_LoanBalance

var old_LoanBalance = db.LoanAccounts
    .Where(a => a.Account_Number == loan_Accountdetails.Account_Number)
    .FirstOrDefault()
    .Account_Balance;

您似乎启用了跟踪,因此当您请求同一实体时,它实际上不会第二次访问数据库。您可以尝试使用ReloadAsync 重新加载它:

await dbContext.Entry(old_LoanBalance).ReloadAsync();

UPD

也可以勾选if entity was already loaded,防止不必要的多次命中数据库:

var existingInContext = db.LoanAccounts
    .Local
    .FirstOrDefault(a => a.Account_Number == loan_Accountdetails.Account_Number);

if(existingInContext != null) db.Entry(existingInContext).Reload();

var old_LoanBalance = db.LoanAccounts
    .Where(a => a.Account_Number == loan_Accountdetails.Account_Number)
    .FirstOrDefault()
    .Account_Balance;

【讨论】:

以上是关于使用 Foreach 循环的问题的主要内容,如果未能解决你的问题,请参考以下文章

foreach跳出循环不往下走

使用java 8中的forEach(..)而不是java 5中的forEach循环的任何优势[重复]

使用 Foreach 循环的问题

foreach和List.Foreach 退出循环相关问题

PHP中使用foreach循环读取数组数据的方法

避免forEach循环时出现问题[重复]