[我想要实现的是每天计算利息[DailyLoanCalculation],然后在月底获取每个帐户的总计并保存在[总利息]表中。每个月都会发生相同的事情
我有一个表DailyLoanCalculation,其中每天的每一天都要计算我的每日利息。我已经能够实现这一目标。
DailyLoanCalculation table
Day Account No Loan interest Amount Per day
1 12345 3000 150
1 23456 1000 50
1 43567 2500 125
2 12345 3000 150
2 23456 1000 50
2 43567 2500 125
Total-Interest Table
Day Account No Loan Total Interest Total
30 12345 3000 4500 7500
30 23456 1000 1500 2500
30 43567 2500 3750 6250
现在要实现[总计]中的问题。这是我一直在努力但无法继续进行的工作
//Calculate the EndOfMonthDailyInterestCalculation
public void EndOfMonthDailyInterestCalculation()
{
IEnumerable<DailyInterest> loans = null;
using (var conn = new SqlConnection(ConnectionString))
{
conn.Open();
loans = conn.Query<DailyInterest>("Select * from DailyInterest where BackgroundMonthly is Null");
if (loans.Count() == 0)
{
return;
}
var TotalEachLoanInterest = loans.GroupBy(x => x.LoanAccountNo).Select(g =>g.Sum(x=>x.AmountPerDay));
**//I cant go further at this point**
if (TotalEachLoanInterest.Count() == 0)
{
return;
}
else
{
foreach (var loan in loans)
{
var SumOfInteretForTheMonth = loan.
var markDailyAsCalculated = new
{
amountPerday = loan.AmountPerDay
};
}
}
}
}
如果有更好的解决方法,请帮帮我谢谢
您的声明:
loans = conn.Query<DailyInterest>
("Select * from DailyInterest where BackgroundMonthly is Null");
此语句后的借贷不再为空。它可能是空序列,但不为空。
改进#1:不要测试贷款中的元素数量。如果序列为空,则以下语句将不执行任何操作。此外,如果您只想知道是否至少有一笔贷款,为什么要计数()全部一千笔贷款:
if (loans.Any())
这将停止枚举第一笔贷款。 Count()将枚举所有贷款。
var TotalEachLoanInterest = loans.GroupBy(x => x.LoanAccountNo)
.Select(g =>g.Sum(x=>x.AmountPerDay));
这不是您想要的。您使用相同的LoanAccountNo组成一组贷款。之后,您获取每组贷款,获取每笔Loan.AmountPerDay并将其相加。结果是一系列求和。您不知道这笔款项所属的LoanAccountNo。
改进#2:考虑overload of Enumerable.GroupBy that has a resultSelector:
var loanInterestTotals = loans.GroupBy(
loan => loan.LoanAccountNo, // keySelector: group by same LoanAccountNo
(accountNo, loansWithThisAccountNo) => new // resultSelector: take each loanAccountNo
{ // and all loans with this accountNo
// to make one new object
LoanAccountNo = accountNo,
TotalInterests = loansWithThisAccountNo
.Select(loan => loan.AmountPerDay)
.Sum(),
});
结果:一个LoanAccountNo序列,每个序列的总和为AmountPerDay。注意:该序列尚未枚举!
您有一个表TotalInterests。显然,您已经知道如何填写属性Day,AccountNo和Loan。您要做的就是知道如何填写属性InterestsTotal
我不确定表interestingTotal是数据库表还是程序中的表。
改进3:保持数据库规范化
我不确定是否有一个单独的包含这些总数的表格是否明智。如果这样做,您将失去一些数据库规范化功能。只要一个表中的兴趣之一发生变化,就必须更新interestTotal表。这应该表明您在多个表中具有相同的信息。
如果InterestsTotal是一个表,请考虑删除该表,并创建一个Dapper SQL或LINQ查询,该查询从表DailyLoanCalculations中获取信息。您的存储库类的用户将不会注意到interestTotal序列是在计算的,而不是单独的表。
[如果您确实想要一个单独的InterestTotals表,那么您应该在一个SQL更新调用中更新InterestsTotal表和DailyLoanCalculations。这样,您可以确定没有人可以从DailyLoanCalculations中获取更新的值,而InterestTotals中的值尚未更新。
LINQ永远不会更改源,因此要更新TotalInterests表,您必须枚举。如果您使用实体框架,则可以获取必须在一个数据库访问中更新的所有interestTotal:
foreach (var loanInterestTotal in loanInterestTotals)
{
// entity framework method: fetch the TotalInterestToUpdate with the same LoandAccountNo
var totalInterestToUpdate = dbContext.TotalInterests
.Where(totalInterest => totalInterest.LoanAccountNo == loanInterestTotal.LoanAccountNo)
.FirstOrDefault();
totalInterestToUpdate.TotalInterest = loanInterestTotal.TotalInterests;
}
dbContext.SaveChanges()
如果使用Dapper,您可能可以一次性更新数据。您比我更了解SQL。
如果InterestsTotal不是数据库表
在那种情况下,请考虑TotalInterests表的(Group-)join与TotalEachLoanInterest。如果要在结果中还需要不在TotalEachLoanInterest中的TotalInterests,则将需要GroupJoin。否则,简单的连接就足够了。
var result = TotalInterests.Join(TotalEachLoanInterests,
totalInterest => totalInterest.AccountNo, // from each totalIntere take the AccountNo,
totalEachLoanInterest => totalEachLoanInterest.AccountNo, // from each totalEachLoanInterest take the account no
(totalInterest, totalEachLoanInterest) => new // when they match make one new
{
Day = totalInterest.Day,
AccountNo = totalInterest.AccountNo,
Loan = TotalInterest.Loan
TotalInterest = totalEeachLoanInterest.TotalInterests,
Total = TotalInterest.Loan + totalEeachLoanInterest.TotalInterests,
});
顺便说一句:您是否注意到我仍然没有列举任何这些LINQ语句?
要获得最终结果,只需使用ToList()。如果原始贷款顺序为空,则结果也将为空。因此,无需对原始贷款进行Count()。
var endResult = result.ToList();
我必须承认,当数据库看起来可以执行此操作时,为什么我要在C#中执行此计算,我有些困惑:
public void EndOfMonthDailyInterestCalculation()
{
IEnumerable<TotalInterest> loans = null;
using (var conn = new SqlConnection(ConnectionString))
{
//conn.Open(); //you don't need to open the conn - Dapper knows how
loans = conn.Query<TotalInterest>("Select MAX(day) as Day, AccountNo, Loan, SUM(InterestAmountPerDay) as TotalInterest, Loan + SUM(InterestAmountPerDay) as Total from DailyInterest WHERE BackgroundMonthly is Null GROUP BY AccountNo, Loan");
...