嘿大家,当我将我的存储库映射到View Model时,我的MVC3应用程序中的数据库查询被杀了。 View非常复杂,主要对象是Assignment
,但View也会从其中的一些关系中返回数据。查看模式看起来像这样
public int Id { get; set; }
public DateTime? RelevantDate { get; set; }
public String Name { get; set; }
public String ProcessName { get; set; }
public String Status { get; set; }
public String Assignee { get; set; }
public int AssigneeId { get; set; }
public bool HasAttachment { get; set; }
public bool IsGroupAssignee { get; set; }
public bool Overdue { get; set; }
public List<String> AvailableActions { get; set; }
public Dictionary<String, String> AssignmentData { get; set; }
public Dictionary<String, String> CompletionData { get; set; }
public List<Transactions> Comments { get; set; }
public List<Transactions> History { get; set; }
public List<File> Files { get; set; }
那里有很多东西,但所有数据都与View相关。在我的存储库中,我使用.Include
显式加载了所有必需的关系(我正在使用实体框架),但是在我开始遍历列表之前,数据实际上并未加载。
var _assignments = (from ctx.Assignments
.Include("Process").Include("Files")
.Include("AssignmentDataSet")
.Include("Transactions")
.where w.Tenant.Id == _tenantId
select w);
在我的控制器中,我在存储库上调用一个方法,该方法使用类似于此的查询来获取我的数据。一些变化,但没有什么不同于上面的。
现在,我正在咀嚼数据库交易。我必须将这些数据导入ViewModel,以便我可以显示它。
private IList<AssignmentViewModel> CreateViewModel(IEnumerable<Assignment> aList)
{
var vList = new List<AssignmentViewModel>();
foreach (var a in aList)
{
var assigneeId = a.Assignee;
vList.Add(new AssignmentViewModel()
{
Id = a.Id,
AssigneeId = (int) a.Assignee,
HasAttachment = (a.Files.Count > 0),
Name = a.Name,
IsGroupAssignee = a.AssignedToGroup,
ProcessName = a.Process.Name,
RelevantDate = a.RelevantDate,
Status = a.Status,
AvailableActions = _assignmentRepository.GetAvailableActions(_user, a),
Assignee =
_users.Where(i => i.Id == assigneeId).Select(v => v.FullName).
FirstOrDefault(),
AssignmentData =
a.AssignmentDataSet.Where(st => st.State == "Assign").ToDictionary(
d => d.Name, d => d.Value),
CompletionData = a.AssignmentDataSet.Where(st => st.State == "Complete").ToDictionary(
d => d.Name, d => d.Value),
Comments = a.Transactions.Where(t => t.Action == "New Comment").ToList(),
History = a.Transactions.Where(t => t.Action != "New Comment").ToList(),
Overdue =
a.RelevantDate >= DateTime.UtcNow.AddHours(-5) || a.RelevantDate == null ||
a.Status == "Complete" || a.Status == "Canceled"
? false
: true
});
}
return vList;
}
这导致每Assignment
个大约2.5分贝的查询。此视图最多可返回30个结果。这对我的数据库有很多打击。不用说,页面很慢。响应时间为5-7秒。我很尴尬!我只是想在这里做太多,或者我只是做错了?
如何优化此功能?
答案 0 :(得分:3)
我能看到两件事:
HasAttachment = (a.Files.Count > 0),
只需使用Any()
,这样您就不必迭代所有文件,假设这仍然是IEnumerable
:
HasAttachment = a.Files.Any(),
另一件事是评论和历史:
Comments = a.Transactions.Where(t => t.Action == "New Comment").ToList(),
History = a.Transactions.Where(t => t.Action != "New Comment").ToList(),
您可以在创建AssignmentViewModel
之前通过实现完整列表来组合这些调用,然后只需采用相应的部分:
var transactions = a.Transactions.ToList();
vList.Add(new AssignmentViewModel()
{
..
Comments = transactions.Where(t => t.Action == "New Comment").ToList(),
History = transactions.Where(t => t.Action != "New Comment").ToList(),
}
如果您必须支持这种显示数据的方式,您应该考虑数据库中的一个视图和相应的实体,它使用连接为您选择所有或大多数相应的数据,因此您需要花费大量精力来UI的数据要少得多。