【发布时间】:2017-05-09 09:50:47
【问题描述】:
我在一个 ASP.NET MVC 应用程序中工作并且有两个不同的连接(数据库)。这就像一个应用程序,用户可以在其中进行一些小型考试。在一个页面上,我必须向用户显示所有包含详细信息的考试/活动:时间、结果以及有关活动/考试的所有详细信息。在红色数据库中仅包含有关结果、时间、用户和活动 ID 的信息 - 因此您可以在另一个(蓝色)数据库中获取该跟踪的活动。每个活动最多可进行 5 次。
我尝试了几个不同的查询,但性能非常非常慢。你有什么想法我该如何解决这个查询并且用户不必在页面上等待 10 秒?
谢谢!
编辑:
跟踪表(db1,表 1)现在有 1732982 条记录,并且一直在增长,因为用户可以随时进行考试。目前有 1832 项活动来自 110 节课。
下面的详细数据库图片(这是我得到的,所以我必须使用它,但如果需要我可以更改 ids/pk/fk - 或更改我需要的任何内容,但它必须保留在两个不同的数据库中):
这是用于为一位用户获取结果的代码。 UserId 像函数中的参数一样发送并在此代码中使用。
IList<TrackingCustomModel> result = new List<TrackingCustomModel>();
using (DATA.examContent.Model ctc = new DATA.examContent.Model()) //first database (activities, lessons)
{
using (Model ctx = new Model()) //this is second database (tracking)
{
// Get all Activities
IList<Activity> ac = ctc.Activity.Include("Lesson").ToList();
char[] trimChars = { '0' };
IEnumerable<TrackingCustomModel> q;
q = from a in ac
select new TrackingCustomModel
{
ActivityId = a.Id,
LessonCode = a.Lesson.Code.TrimStart(trimChars),
ActivityCode = a.Code.TrimStart(trimChars),
ActivityHead = a.Head.Trim()
};
IList<TrackingCustomModel> add = q.ToList<TrackingCustomModel>();
// Get all Trackings for userId
IList<Tracking> tr = ctx.Tracking.Where(t => t.UserId == userId).ToList();
// Join Activites with Tracking of User, and Calculate Scores
var s = from a in add
join t in tr on a.ActivityId equals t.ActivityId
orderby t.Timestamp descending
select new TrackingCustomModel
{
ActivityId = a.ActivityId,
LessonCode = a.LessonCode,
ActivityCode = a.ActivityCode,
ActivityHead = a.ActivityHead,
Timestamp = DefaultHelper.AdjustDateToLocalTimezone(t.Timestamp),
ActivityHits = t.ActivityHits,
ActivityMistakes = t.ActivityMistakes,
ActivityScore = (t.ActivityHits + t.ActivityMistakes) > 0 ? (String.Format("{0:0%}", (Decimal.Divide(t.ActivityHits, (t.ActivityHits + t.ActivityMistakes))))).ToString() : null
};
// Group the results by Activity and calculate the Activity average
var group = from t in s
group t by t.ActivityId into g
select g;
foreach (IGrouping<Guid, TrackingCustomModel> g in group)
{
TrackingCustomModel thc = (from t in g
where t.ActivityId == g.Key
select t).FirstOrDefault();
IList<TrackingCustomModel> multipleTry = (from d in s
where d.ActivityId == g.Key
select d).ToList();
if (multipleTry.Count > 1)
{
thc.ActivityDone = multipleTry.Count.ToString();
Decimal scoreAsDecimal;
Decimal averageScore = 0;
foreach (TrackingCustomModel t in multipleTry)
{
if (t.ActivityHits != 0)
{
scoreAsDecimal = (Decimal.Divide(t.ActivityHits, (t.ActivityHits + t.ActivityMistakes)));
averageScore += scoreAsDecimal;
}
}
averageScore /= multipleTry.Count;
if (averageScore != 0)
{
thc.AverageScore = String.Format("{0:0%}", averageScore).ToString();
}
else
{
thc.AverageScore = "";
}
}
else
{
thc.ActivityDone = "";
}
result.Add(thc);
}
}
}
return result;
【问题讨论】:
-
您需要显示您正在执行的代码和查询。还有表格上的任何相关索引。
-
因为您使用的是 LINQ 和两个不同的数据库,您可能会陷入一个常见的陷阱,即将每个结果集的所有数据拉回内存,然后使用 LINQ to 对象连接它们。除非您发布代码 sn-p,否则无法确定。
-
什么是查询慢?
-
我添加了一些信息和代码!谢谢大家!
-
您应该测量代码中的步骤,创建
add、tr和实际连接。确定最耗时的步骤。如前所述,连接是在内存中完成的。
标签: c# asp.net-mvc linq