문제

I have a query I'm executing in LinqPad (EF4 against a SQL2010 backend), which uses navigation properties to access related tables. I don't really have access to fiddle with indexes and so forth, and was wondering if there are any ways to avoid all the subqueries inherent in those 'firstordefault' items toward the bottom of the query. I've tried using a 'let' statement at the top as in "let accounts = i.ExpenseItemAccountings.FirstOrDefault()" and then use that reference to make it run only one subquery, but it still takes easily more than an hour to run this query for any meaningful number of records.

Is there any way I can make this more efficient?

    var output = from i in ExpenseItems where
i.Er_Approved_Date >= fromDate &&
i.Er_Approved_Date <= toDate
select new {ER_Num = i.ErNum,
         Line_Num = i.ItemNum,
         Report_Title = i.Report_Title,
         Requestor = i.Requester_Name,
         Preparer = i.Preparer_Name,
         ER_Total_Value = i.Er_TotalVal,
         Partition = i.Org,
         Transaction_Date = i.Item_Transaction_Date,
         Approved_Date = i.Er_Approved_Date,
         Item_Amount = i.Item_Amount,
         Tips = i.Item_Tips,
         GST = i.Item_Gst,
         Have_Receipt = i.Item_Have_ReceiptTf,
         Have_Invoice = i.Item_Have_InvoiceTf,
         Vendor = i.Item_Vendor,
         City = i.Item_City,
         Item_Expense_Type = i.Item_Expense_Type,
         Item_Description = i.Item_Expense_Description,
         Misc_Item_Commodity = i.Item_Misc_Commodity_Name,
         Misc_Item_SubCategory = i.Item_Misc_Specify,
         Misc_Item_OtherMisc_Description = i.Item_Misc_Specify_Other_Desc,
         Entity_Num = i.ExpenseItemAccountings.FirstOrDefault().Item_Entity_Num,
         Entity_Name = i.ExpenseItemAccountings.FirstOrDefault().Item_Entity_Name,
         Account_Num = i.ExpenseItemAccountings.FirstOrDefault().Item_Account_Num,
         Account_Desc = i.ExpenseItemAccountings.FirstOrDefault().Item_Account_Name,
         SubAccount_Num = i.ExpenseItemAccountings.FirstOrDefault().Item_SubAccount_Num,
         SubAccount_Name = i.ExpenseItemAccountings.FirstOrDefault().Item_SubAccount_Name,
         CostCentre_Num = i.ExpenseItemAccountings.FirstOrDefault().Item_CostCentre_Num,
         CostCentre_Name = i.ExpenseItemAccountings.FirstOrDefault().Item_CostCentre_Name,
         Project_Code = i.ExpenseItemAccountings.FirstOrDefault().Expense_Item_ProjectCode,
         ////Percent_Allocated = i.ExpenseItemAccountings.FirstOrDefault().Item_Percent,
         ER_Comments = i.Er_Comments,
         Item_First_Comment = i.ExpenseItemComments.FirstOrDefault().Comment_Content,
         Violations = i.ExpenseItemViolations.Count()
                      };
도움이 되었습니까?

해결책

On LinqPad you should be able to view the SQL statement generated from the LINQ statement.

In my opinion there is always a debate between using let or navigation properties in LINQ to Entities (or LINQ to SQL). Sometimes a simple JOIN might work better too. In other words it all depends on how your LINQ provider (Entity Framework) optimizes your specific query into SQL statements.

I would suggest you test your query with all let/join/navigation to see the generated SQL statement.

You can use ObjectQuery under System.Data.Objects in your code to view realtime SQL statement in case you don't have SQL profiler or intellitrace tool:

((ObjectQuery)anyLinqQuery).ToTraceString();

Also you can try using multiple from clause:

var output = from i in ExpenseItems
             from exp in i.ExpenseItemAccountings
             where ....
             select new {...};

or

var output = from i in ExpenseItems
             from exp in i.ExpenseItemAccountings.DefaultIfEmpty()
             where ....
             select new {...};
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top