我有一个WPF应用程序,它使用web-Service来获取记录列表。 此列表通常只包含3到6条记录,每条记录大约有4到7个属性。
但是要计算这些结果,我必须遍历LINQ语句。 例如:请参阅下面的代码(注意此代码(用于的方法)执行嵌套迭代以获取值):
public List<ReturnType> CalculateSomeResult(DateTime startDate, DateTime endDate, int tempID)
{
//Start here...
List<ReturnType> listResult = new List<ReturnType>();
string aFormula = GetaFormula(tempID); // net worth
int index = int.Parse(aFormula);
SomeResult resultTotal = new SomeResult();
resultTotal.NetWorth = getBeforeEndDate(index, tempID, 0, endDate);
decimal[] incomes = CalculateProfit(startDate, endDate, tempID);
decimal[] expenses = CalculateExpense(startDate, endDate, tempID);
resultTotal.old = incomes[0] - expenses[0];
resultTotal.current = incomes[1] - expenses[1];
resultTotal.EndingNetWorth = resultTotal.NetWorth
+ resultTotal.old
+ resultTotal.current;
ReturnType tempValTotal = new ReturnType();
tempValTotal.objSomeResult = resultTotal;
tempValTotal.Name = "Total";
ReturnType tempVal = new ReturnType();
using (DCMyDataContext context = new DCMyDataContext())
{
try
{
var currentEntity = context.Persons.Where(x => x.ID == tempID).FirstOrDefault();
var contactList = getCByT(CT.I_O, tempID).OrderBy(x => x.ID).ToList();
//This is where, it converts the DB String column value into
//JSON Object list
List<jsonVal> jsonVals = jsonVal.fromJson<List<jsonVal>>(currentEntity.jsonVal);
foreach (Contact contact in contactList)
{
var objA = jsonVals.Where(x => x.ContactID == contact.ID &&
((x.EndDate.HasValue == false) ||
(x.EndDate.HasValue == true &&
((x.StartDate >= startDate && x.StartDate <= endDate) ||
(x.EndDate.Value >= startDate && x.EndDate.Value <= endDate)))));
var objPreviousA = jsonVals.Where
(x => x.ContactID == contact.ID &&
((x.EndDate.HasValue == false) ||
((x.EndDate.HasValue == true && (x.StartDate < startDate || x.EndDate.Value < startDate)))));
if (objA.Any() || objPreviousA.Any())
{
}
else
{
continue;
}
SomeResult result = new SomeResult();
result.NetWorth = getBeforeEndDate(index, tempID, contact.ID, endDate);
decimal oldIncome = 0;
decimal oldExp = 0;
decimal cIncome = 0;
decimal cExp = 0;
decimal lastaPercent = 0;
decimal lastIncomePercent = 0;
var lastjsonValRecord = objA.OrderByDescending(x => x.StartDate);
if (lastjsonValRecord.Any())
{
if (lastjsonValRecord.FirstOrDefault().a.HasValue)
lastaPercent = lastjsonValRecord.FirstOrDefault().a.Value;
if (lastjsonValRecord.FirstOrDefault().Income.HasValue)
lastIncomePercent = lastjsonValRecord.FirstOrDefault().Income.Value;
}
IEnumerable<int> incomeIDs = GetLeafAccountIDs(5, tempID);
IEnumerable<int> expenseIDs = GetLeafAccountIDs(6, tempID);
if (objA.Any())
{
foreach (jsonVal ownerRec in objA.ToList())
{
DateTime dtEnd = endDate;
if (ownerRec.EndDate.HasValue)
dtEnd = ownerRec.EndDate.Value;
if (dtEnd > endDate)
dtEnd = endDate;
DateTime dtStart = ownerRec.StartDate;
if (ownerRec.StartDate <= startDate)
dtStart = startDate;
decimal incomePercent = 0;
if (ownerRec.Income.HasValue) incomePercent = ownerRec.Income.Value;
if (incomePercent > 0 )
{
foreach (int id in incomeIDs)
{
decimal bal = CalculateB(id, dtStart, dtEnd);
cIncome += (bal * incomePercent / 100m);
}
foreach (int id in expenseIDs)
{
decimal bal = CalculateB(id, dtStart, dtEnd);
cExp += (bal * incomePercent / 100m);
}
}
}
}
if (objPreviousA.Any())
{
foreach (jsonVal ownerRec in objPreviousA.ToList())
{
DateTime dtEnd = endDate;
DateTime dtStart = ownerRec.StartDate;
if (ownerRec.EndDate.HasValue)
dtEnd = ownerRec.EndDate.Value;
if (dtEnd > startDate)
dtEnd = startDate;
if (dtStart > startDate)
dtStart = startDate;
decimal incomePercent = 0;
if (ownerRec.Income.HasValue) incomePercent = ownerRec.Income.Value;
if (incomePercent > 0 && ownerRec.StartDate > new DateTime(1, 1, 1))
{
foreach (int id in incomeIDs)
{
decimal bal = CalculateB(id, dtStart, dtEnd);
oldIncome += (bal * incomePercent / 100m);
}
foreach (int id in expenseIDs)
{
decimal bal = CalculateB(id, dtStart, dtEnd);
oldExp += (bal * incomePercent / 100m);
}
}
}
}
result.old = oldIncome - oldExp;
result.current = cIncome - cExp;
result.EndingNetWorth = result.NetWorth
+ result.old
+ result.current;
tempVal = new ReturnType();
tempVal.objSomeResult = result;
tempVal.Name = contact.FirstName;
listResult.Add(tempVal);
}
}
catch
{
}
}
listResult.Add(tempValTotal);
//Reach here after 15 seconds...
return listResult;
}
当我调试此代码时,需要1个15秒才能到达return语句。
我试图将整个处理转换为SQL Stored proc,可能会提高处理速度。但我有一个块点,在数据库表中我将Json字符串存储在一列和一列中。这里使用的结果来获得结果。
我知道我需要创建自定义功能以将其解析为SQL中的相关表对象。或者我需要更改将Json字符串保存到列中的默认行为,以将其保存到新表中。
但这对我来说需要花费很多时间。 我需要任何建议,以加快处理速度。 我会考虑所有&amp;选择那个适合我的。
由于
答案 0 :(得分:0)
您应该运行调试会话并找到大部分时间占用的确切行。几乎不可能在工作环境中为你检查代码(它可能是很多东西,sql转换.ToList()需要太长时间,缺少索引,有几个调用到其他一些方法,等等)
如果您运行调试会话,则可以登录每个&#34;部分&#34;该代码,然后注意大部分时间的部分,并将注意力集中在该特定行,以找到解决方案。
答案 1 :(得分:0)
减少您正在进行的查询次数。既然您知道自己需要为每个联系人运行objA
和objPreviousA
,而不是一次只获取一个联系人,请抓住所有联系人并在一次调用中将它们放入列表/字典中,然后将objA / objPreviousA设置为循环中的适当值。
类似的东西:
var contactIds=contactList.Select(c=>c.id).ToArray();
var objAs = jsonVals.Where(x => contactIds.Any(cid=>cid==x.ContactID) &&
((x.EndDate.HasValue == false) ||
(x.EndDate.HasValue == true &&
((x.StartDate >= startDate && x.StartDate <= endDate) ||
(x.EndDate.Value >= startDate
&& x.EndDate.Value <= endDate)))))
.ToList();
foreach(var contact in contactList)
{
var objA=objAs.Where(a=>a.ContactId==contact.id).ToList();
...
这适用于中小量的记录。如果它变得太大,那么你应该转换为使用Dictionary而不是List,以减少循环中的查找时间。