asp.net MVC 4.0 C#, Visual Studio 2012 professional 사용.로드 3 분 이상 걸리는보기
알았어, 내 컨트롤러에 하나의 작업 결과가 있는데, 그 목적은 다양한 서비스와 모델을 사용하고 표시 할보기 목록으로 데이터를 비정규 화하는 것입니다. 이는 사용자 상호 작용을 기반으로합니다. 간단한 컨트롤을 통해 데이터를 필터링하는 데 사용됩니다.
전체 사이트가 Webforms Sql 프로젝트에서 내부 CMS 솔루션 (CMS는 Nop commerce 및 Orchard를 기반으로 함)을 사용하여 MVC 코드 첫 번째 방법으로 마이그레이션되었습니다.
이제이 컨트롤러 기능은 각 모듈에 대한 코드를 추가 할 때까지 상당히 잘 작동했습니다. 원래는 이전 프로젝트에서했던 것과 똑같은 일을하고 싶었고 데이터를 합친 다음 정규화되지 않은 결과를 사용하여 교차 분석을 사용했습니다.
그러나 SQL에서 코드로 처음 전송할 때 교차 쿼리를 모방 할 수 있는지는 확실하지 않았습니다.
이로 인해 많은 루프가 생성되었습니다. 여기에는 컨트롤러 동작 방법과 비 동작이 있습니다.
public ActionResult Index(UsersModel model)
{
model.DateTo = model.DateTo.AddDays(1);
if (model.DateFrom == null || model.DateTo == null || model.DateFrom == DateTime.MinValue || model.DateTo == DateTime.MinValue.AddDays(1))
{
// default to last 30 days
model.DateFrom = _clock.UtcNow.AddDays(-30);
model.DateTo = _clock.UtcNow;
}
var userQuery = _academyUserService.Query()
.Where(x => x.Activity.DateRegistered >= model.DateFrom && x.Activity.DateRegistered <= model.DateTo);
var quizCompletedQuery = _quizService.QueryQuizHistoryCompleted()
.Where(x => x.DateCompleted >= model.DateFrom && x.DateCompleted <= model.DateTo);
var quizHistoryQuery = _quizService.QueryHistory()
.Where(x => x.DateCompleted >= model.DateFrom && x.DateCompleted <= model.DateTo);
var moduleQuery = _moduleService.Query()
.Where(x => x.Published);
//admin country selected, null = global
if (_moServices.WorkContext.HttpContext.Session["AdminAreaCurrentCulture"] != null)
{
userQuery = userQuery.Where(x => x.UserCountry.CountryCulture.Culture == _moServices.WorkContext.HttpContext.Session["AdminAreaCurrentCulture"].ToString());
quizCompletedQuery = quizCompletedQuery.Where(x => x.Country.CountryCulture.Culture == _moServices.WorkContext.HttpContext.Session["AdminAreaCurrentCulture"].ToString());
quizHistoryQuery = quizHistoryQuery.Where(x => x.Module.Country.CountryCulture.Culture == _moServices.WorkContext.HttpContext.Session["AdminAreaCurrentCulture"].ToString());
moduleQuery = moduleQuery.Where(x => x.Country.CountryCulture.Culture == _moServices.WorkContext.HttpContext.Session["AdminAreaCurrentCulture"].ToString());
}
if (!string.IsNullOrEmpty(model.Name))
{
userQuery = userQuery.Where(x => x.FirstName.Contains(model.Name) || x.Surname.Contains(model.Name));
}
if (!string.IsNullOrEmpty(model.AccountType))
{
userQuery = userQuery.Where(x => x.AccountType.ToString() == model.AccountType);
}
if (!string.IsNullOrEmpty(model.Company))
{
userQuery = userQuery.Where(x => x.BusinessName == model.Company);//placeholder intefering with this?
}
if (!string.IsNullOrEmpty(model.Code))
{
userQuery = userQuery.Where(x => x.RegistrationCode.Contains(model.Code));
}
if(true)//cant condition an Iquery as its not a list...)//temp
{
//quizCompletedQuery = quizCompletedQuery.Where(x => x.Country.CountryCulture.Culture == _moServices.WorkContext.HttpContext.Session["AdminAreaCurrentCulture"].ToString());
}
//new code
var groupedModules = moduleQuery
.OrderBy(x => x.DisplayOrder)
.ToList()
.GroupBy(x => x.Country)
.SelectMany(group => group.Select((x, i) => new { Index = i, Module = x }))
.GroupBy(anon => anon.Index)
.Select(group => group.Select(x => x.Module).ToList())
.ToList();
var historyResults = quizHistoryQuery.ToList();
//my old code
PrepareBusinessNames(model);
var usersToModel = userQuery.ToList().Select(x =>
{
bool thisHistoryPassed1 = false;
bool thisHistoryPassed2 = false;
bool thisHistoryPassed3 = false;
bool thisHistoryPassed4 = false;
if (groupedModules.Count > 0)
{
var module1 = groupedModules[0];
var moduleIds1 = module1.Select(y => y.Id).ToList();
var thisHistory1 = quizHistoryQuery.Where(y => y.User.Id == x.Id && moduleIds1.Contains(y.Module.Id));
thisHistoryPassed1 = thisHistory1.Any(_quizService.IsHistoryPassed);
}
if (groupedModules.Count > 1)
{
var module2 = groupedModules[1];
var moduleIds2 = module2.Select(y => y.Id).ToList();
var thisHistory2 = quizHistoryQuery.Where(y => y.User.Id == x.Id && moduleIds2.Contains(y.Module.Id));
thisHistoryPassed2 = thisHistory2.Any(_quizService.IsHistoryPassed);
}
if (groupedModules.Count > 2)
{
var module3 = groupedModules[2];
var moduleIds3 = module3.Select(y => y.Id).ToList();
var thisHistory3 = quizHistoryQuery.Where(y => y.User.Id == x.Id && moduleIds3.Contains(y.Module.Id));
thisHistoryPassed3 = thisHistory3.Any(_quizService.IsHistoryPassed);
}
if (groupedModules.Count > 3)
{
var module4 = groupedModules[3];
var moduleIds4 = module4.Select(y => y.Id).ToList();
var thisHistory4 = quizHistoryQuery.Where(y => y.User.Id == x.Id && moduleIds4.Contains(y.Module.Id));
thisHistoryPassed4 = thisHistory4.Any(_quizService.IsHistoryPassed);
}
return new UsersSearchModel
{
UserID = x.Id,
Name = x.FirstName,
Surname = x.Surname,
Company = x.BusinessName,
AccountType = x.AccountType.ToString(),
UserCode = x.RegistrationCode,
VideosViewed = "", //x.VideoActivity.ToString(),
Module1 = thisHistoryPassed1,
Module2 = thisHistoryPassed2,
Module3 = thisHistoryPassed3,
Module4 = thisHistoryPassed4,
Module1Url = thisHistoryPassed1 ? Url.Content("~/Areas/Admin/Media/Images/checked.png") : Url.Content("~/Areas/Admin/Media/Images/unchecked.png"),
Module2Url = thisHistoryPassed2 ? Url.Content("~/Areas/Admin/Media/Images/checked.png") : Url.Content("~/Areas/Admin/Media/Images/unchecked.png"),
Module3Url = thisHistoryPassed3 ? Url.Content("~/Areas/Admin/Media/Images/checked.png") : Url.Content("~/Areas/Admin/Media/Images/unchecked.png"),
Module4Url = thisHistoryPassed4 ? Url.Content("~/Areas/Admin/Media/Images/checked.png") : Url.Content("~/Areas/Admin/Media/Images/unchecked.png")
};
}).ToList();
var jsonSerialiser = new JavaScriptSerializer();
var jsonString = jsonSerialiser.Serialize(usersToModel);//or is it model? or a list of model?
model.REFACTOR_ForJson = jsonString;
return View(model);
}
#region utilities
[NonAction]
private UsersModel PrepareBusinessNames(UsersModel model)
{
if (_moServices.Authoriser.Authorise(DefaultPermissions.AccessAdminPanel))
{
var listItems = _academyUserService.GetAllBusinessNames().Select(x =>
{
return new SelectListItem
{
Value = x,
Text = x
};
}).OrderBy(x => x.Value)
.ToList();
model.CurrentBusinessNames = new SelectList(listItems, "Value", "Text");
}
return model;
}
사용자 목록을 반환하고 필터를 기반으로 모듈을 나타내는 4 개의 열이있는 목록을 표시하고 전달되었는지 여부는 알 수 있습니다.
내가 말했듯이, 통과 또는 통과되지 않은 부울 값을 얻기위한 코드를 추가하면 내 쿼리가 촬영되어 오랜 시간이 걸립니다.
기존 코드를 수정하여 문제를 해결할 수있는 방법이 있습니까? 아니면 교차 쿼리와 비슷한 방법을 사용하여 기능을 다시 작성할 수있는 솔루션입니까?
당신의 팁 주셔서 감사합니다!
업데이트 ::
을 heres 프로파일 결과, 난 임 여기에서 무엇을 찾고 메신저 확실하지 전에를 사용한 적이있다.
은 부품 및 진술하면 다른이 definatly SEMS의 주요 느린 반응의 원인으로 "(groupedModules.Count> 0)의 경우를"주석. 그래서 이전에 물어 보았 듯이 결과를 얻는 더 좋은 방법이 있습니까?if (groupedModules.Count > 0)
{
var module1 = groupedModules[0];
var moduleIds1 = module1.Select(y => y.Id).ToList();
var thisHistory1 = historyResults.Where(y => y.User.Id == x.Id && moduleIds1.Contains(y.Module.Id));
thisHistoryPassed1 = thisHistory1.Any(_quizService.IsHistoryPassed);
}
대신 iquerable를 사용하여
if (groupedModules.Count > 0)
{
var module1 = groupedModules[0];
var moduleIds1 = module1.Select(y => y.Id).ToList();
var thisHistory1 = quizHistoryQuery.Where(y => y.User.Id == x.Id && moduleIds1.Contains(y.Module.Id));
thisHistoryPassed1 = thisHistory1.Any(_quizService.IsHistoryPassed);
}
을 대체 ::
업데이트는, 내가 역사는 다음 대신 목록을 사용 tolist. 이렇게하면로드 시간이 6 분에서 15 초로 크게 단축됩니다. 그러나 이것이 모두 여전히 느린 것으로 알고 있으므로 유일한 결론은이 코드가 선택 목록에 있어야한다는 사실입니다. 프로세스를 다시 할 수있는 방법이 있습니까?
var thisHistory1 = quizHistoryQuery.Where(y => y.User.Id == x.Id && moduleIds1.Contains(y.Module.Id));
쿼리를 다시 실행 원인 :
yeh 내 첫 번째 문장은 tolist를 제거하는 것이었지만이 방법으로는 0 번의 개선이있었습니다. 주말에 선두에 추가 된대로이 문장을 남겼습니다. – lemunk
실제 성능 측정 도구를 사용해 보셨습니까? SQL 프로파일 러 및 외부 도구를 사용하여 쿼리를 프로파일 링 했습니까? –