2013-04-27 2 views
1

MVC3에서 Entity Framework로 프로젝트를 수행하고있었습니다. 나는 LINQ에 많은 경험이 없다. 그러나 필자는 필자의 요구 사항에 따라 코드를 관리했다. 문제는, 내 논리가 foreach을 사용하는 쿼리를 분할하여 쿼리를 처리하는 데 더 많은 시간이 걸리고 DB의 단일 열에 세 가지 유형이 있습니다. LINQ 자체를 사용하여 전체 논리를 코딩하려고했습니다. 하지만 아무것도 도와주지 않았어.더 나은 LINQ 쿼리를 만드는 방법

내 코드 성능을 향상시키기 위해 논리를 어떻게 바꿀 수 있습니까? Pls이 나를 도와줍니다.

작업 방법 코드

 public decimal ReturnAmount(int Id, int Year) 
    { 

     var UsersWithDeptId = db.Users.Where(asd => asd.UserDeptId == Id).Select(asd => asd.Id).ToList(); 
     var ListUserValue = (from cap in db.CareAllocationPercents 
          where cap.Type == 1 && UsersWithDeptId.Contains(cap.UserId) 
          select new UserWithDeptId 
          { 
           Year = (from amt in db.CareAllocations where amt.CareItemId == cap.CareItemId select amt.Year).FirstOrDefault(), 
           Amount = (from amt in db.CareAllocations where amt.CareItemId == cap.CareItemId select amt.Amount).FirstOrDefault(), 
           UserId = cap.UserId, 
           UserDeptId = (from userdept in db.Users where userdept.Id == cap.UserId select userdept.UserDeptId).FirstOrDefault(), 
           Percentage = cap.Percentage, 
           CareItemId = cap.CareItemId, 
           Category = "User", 
           CareAllocationId = cap.Id 
          }).ToList(); 

     ListUserValue = ListUserValue.Where(asd => asd.Year == Year).ToList(); 

     List<int> RouteIds = db.CareAllocationPercents.Where(asd => asd.Type == 3).Select(asd => asd.UserId).ToList(); 
     var UsersWithRoutingId = (from route in db.RoutingListMembers 
            where RouteIds.Contains(route.RoutingListId.Value) && route.User.UserDeptId == Id 
            select 
             new RoutingWithUser 
             { 
              UserId = route.UserId, 
              RoutingId = route.RoutingListId 
             }).ToList(); 

     var ListRouteValue = (from cap in db.CareAllocationPercents 
           where cap.Type == 3 
           select new UserWithDeptId 
           { 
            Year = (from amt in db.CareAllocations where amt.CareItemId == cap.CareItemId select amt.Year).FirstOrDefault(), 
            Amount = (from amt in db.CareAllocations where amt.CareItemId == cap.CareItemId select amt.Amount).FirstOrDefault(), 
            UserId = cap.UserId, 
            UserDeptId = (from userdept in db.Users where userdept.Id == cap.UserId select userdept.UserDeptId).FirstOrDefault(), 
            Percentage = cap.Percentage, 
            Category = "Route", 
            CareItemId = cap.CareItemId, 
            CareAllocationId = cap.Id 
           }).ToList(); 

     List<UserWithDeptId> NewRouteList = new List<UserWithDeptId>(); 
     ListRouteValue = ListRouteValue.Where(asd => asd.Year == Year).ToList(); 

     foreach (var listdept in ListRouteValue) 
     { 
      var user = UsersWithRoutingId.Where(uwri => uwri.RoutingId == listdept.UserId).FirstOrDefault(); 
      if (user != null) 
      { 
       NewRouteList.Add(new UserWithDeptId { UserId = user.UserId, Year = listdept.Year, UserDeptId = db.Users.Where(asd => asd.Id == user.UserId).Select(asd => asd.UserDeptId).FirstOrDefault(), Percentage = listdept.Percentage, CareItemId = listdept.CareItemId, Amount = listdept.Amount, CareAllocationId = listdept.CareAllocationId, Category = listdept.Category }); 
      } 
     } 

     NewRouteList = NewRouteList.Where(asd => asd.UserDeptId == Id).ToList(); 
     var ListUserId = (from user in db.Users 
          where user.UserDeptId == Id 
          select new UserWithDeptId 
          { 
           UserId = user.Id 
          }).ToList(); 

     var ListDeptId = (from cap in db.CareAllocationPercents 
          where cap.Type == 2 && cap.UserId == Id 
          select new UserWithDeptId 
          { 
           Year = (from amt in db.CareAllocations where amt.CareItemId == cap.CareItemId select amt.Year).FirstOrDefault(), 
           Amount = (from amt in db.CareAllocations where amt.CareItemId == cap.CareItemId select amt.Amount).FirstOrDefault(), 
           UserDeptId = cap.UserId, 
           Percentage = cap.Percentage, 
           Category = "Dept", 
           CareItemId = cap.CareItemId, 
           CareAllocationId = cap.Id, 
          }).ToList(); 

     ListDeptId = ListDeptId.Where(asd => asd.Year == Year).ToList(); 
     int UserCount = ListUserId.Count; 
     List<UserWithDeptId> NewList = new List<UserWithDeptId>(); 

     foreach (var listdept in ListDeptId) 
     { 
      foreach (var users in ListUserId) 
      { 
       NewList.Add(new UserWithDeptId { UserId = users.UserId, UserDeptId = listdept.UserDeptId, Percentage = listdept.Percentage, CareItemId = listdept.CareItemId, Amount = listdept.Amount, CareAllocationId = listdept.CareAllocationId, Category = listdept.Category }); 
      } 
     } 
     int CountUser = ListUserValue.Count; 
     int RouteCount = NewRouteList.Count; 
     NewList.AddRange(ListUserValue); 
     NewList.AddRange(NewRouteList); 
     List<CAREReviewBefore> NewModelList = new List<CAREReviewBefore>(); 
     foreach (var mod in NewList) 
     { 
      CAREReviewBefore cr = new CAREReviewBefore(); 
      // int? BibId = (from pod in db.PoDetails where pod.Id == (from por in db.CareItems where por.Id == mod.CareItemId select por.PoReceipt.PoDetailId).FirstOrDefault() select pod.BibId).FirstOrDefault(); 
      int? InvoiceId = (from asd in db.PoReceipts 
           where asd.Id == (from careits in db.CareItems where careits.Id == mod.CareItemId select careits.PoRecId).FirstOrDefault() 
           select asd.InvoiceId).FirstOrDefault(); 

      //Current Currency Rate 

      var Rate = db.Invoices.Where(In => In.Id == InvoiceId).Select(In => In.Rate).FirstOrDefault(); 
      var CurrencyRate = db.Invoices.Where(inv => inv.Id == InvoiceId).Select(inv => inv.Currency.Rate).FirstOrDefault(); 
      decimal Rat = 0; 
      if (Rate != null || Rate != 0) 
      { 
       Rat = Convert.ToDecimal(Rate); 
       if (Rat == 0) 
       { 
        Rat = Convert.ToDecimal(CurrencyRate); 
       } 
       cr.Tot_Annual_SubCost = mod.Amount * Rat; 
      } 

      if (mod.Category == "User") 
      { 
       cr.Allocated_Cost_to_Dept = (((mod.Amount * mod.Percentage)/(100)) * Rat); 
      } 
      else if (mod.Category == "Dept") 
      { 
       cr.Allocated_Cost_to_Dept = (((mod.Amount * mod.Percentage)/(UserCount * 100)) * Rat); 
      } 
      else if (mod.Category == "Route") 
      { 
       cr.Allocated_Cost_to_Dept = (((mod.Amount * mod.Percentage)/(RouteCount * 100)) * Rat); 
      } 
      NewModelList.Add(cr); 

     } 
     var Amount = NewModelList.Sum(asd => asd.Allocated_Cost_to_Dept); 
     return Amount; 
    } 

감사합니다,

+3

많은 코드입니다. –

+0

이처럼 복잡한 쿼리를 만들었을 때 저장된 proc에서 더 좋은 결과를 얻었습니다. Database.SQLQuery <> 메서드를 사용하여 결과를 EF 객체로 푸시합니다. – jfrankcarr

답변

2

당신이하고있는 .ToList() 호출되는 순간에 나에게 붙어있는 유일한 방법. .ToList()IQueryable을 구체화하여 데이터베이스에 대해 쿼리를 실행합니다. 가능한 대부분의 작업을 수행하여 대부분의 쿼리를 테이블 행을 모두 가져 오지 않고 코드에서 필터링하는 대신 데이터베이스에 대해 실행할 수 있도록하는 것이 좋습니다.

다른 제안은 SQL Server 프로파일 러에서 추적을 설정하고 데이터베이스에 대해 실제로 실행중인 쿼리를 보는 것입니다.

0

엔티티 프레임 워크 프로파일 러를 사용하는 것이 좋습니다. nhibernate 프로파일 러를 사용했으며 실제로는 좋았습니다. 슬프게도 무료는 아니지만 평가판 버전은 충분한 시간을줍니다. 마지막 부분에서

from cap in db.CareAllocationPercents 
where (cap.Type == 1 && UsersWithDeptId.Contains(cap.UserId)) 
    || (cap.Type == 2 && cap.UserId == Id) 
    || cap.Type == 3 
select new UserWithDeptId 
{ 
    Year = (from amt in db.CareAllocations where amt.CareItemId == cap.CareItemId select amt.Year).FirstOrDefault(), 
    Amount = (from amt in db.CareAllocations where amt.CareItemId == cap.CareItemId select amt.Amount).FirstOrDefault(), 
    UserId = cap.UserId, 
    UserDeptId = (from userdept in db.Users where userdept.Id == cap.UserId select userdept.UserDeptId).FirstOrDefault(), 
    Percentage = cap.Percentage, 
    CareItemId = cap.CareItemId, 
    Category = "User", 
    CareAllocationId = cap.Id, 
    Type = cap.Type 
}) 

당신이 계산하는 mod.Category 대신에 Type를 사용

http://www.hibernatingrhinos.com/products/EFProf

0

한 개선은 당신이 필터에 필요한 데이터를 가져온 후 1 개 테이크의 목록을 얻을 수 있습니다 오른쪽은 Allocated_Cost_to_Dept입니다.