2011-08-29 105 views
0

一直主要從事Java和新LINQ所以我需要此查詢。我有3個表LINQ到SQL查詢優化

1. Products -->     ProductID | Name | Price | VendorID 
2. Category -->     CategoryID | Label 
3. SubCategory-->     SubCategoryID | Label | ParentID 
4. Product_SubCategory_Mapping--> ProductID | SubCategoryID 
5. Vendor  -->     VendorID | VendorName 

我想沿着選擇從產品表中所有產品的性能的一些建議與其供應商爲任何給定的子類別。應該查詢工作正常嗎?或者它需要任何優化?

var list = (from p in Products 
      join cat in Product_SubCategory_Mapping 
      on p.UserId equals cat.UserId 
      join sub in SubCategories 
      on cat.SubCategoryId equals sub.SubCategoryId 
      where sub.CategoryId == 19 && CustomFunction(p.ID) > 100 
      select new { p, p.Vendor, trend = CustomFunction(p.ID) }) 
      .Skip((pageNum - 1) * pageSize) 
      .Take(pageSize); 

我將創建一個與查詢結果相匹配的自定義類。

  1. 創建一個視圖/存儲過程更好的情況下,像這樣?
  2. 可以CustomFunction(p.ID)> 100命名,所以函數不會被調用兩次嗎?它是數據庫中的自定義函數。
  3. 尋呼將跳過並取得良好表現?
+1

只是一個快速註釋(因爲我的LINQ技能很弱,我不能提供任何有用的建議來真正回答你的問題)......但我不禁注意到你的產品表有一個** ProductID **列,而另外兩個表只有一個** ID **列。我猜這些列代表一個主鍵字段(並且可能,儘管也是一個IDENTITY字段)。如果是這樣,您可能需要考慮在所有表中使名稱保持一致:即Category.ID - > Category.CategoryID或Products.ProductID - > Products。ID。供應商和子類別相同。 –

+0

同意。感謝您的建議。我更改了名稱。我的實際數據庫有正確的名稱。 T –

回答

3

你在正確的軌道上,但LINQ to SQL的不理解CustomFunction()所以你需要切換到LINQ到對象與之前AsEnumerable()你可以調用它。您還可以使用在查詢中使用let捕捉CustomFunction()結果曾經在別處:

var listFromSql = from p in Products 
        join cat in Product_SubCategory_Mapping 
        on p.UserId equals cat.UserId 
        join sub in SubCategories 
        on cat.SubCategoryId equals sub.SubCategoryId 
        where sub.CategoryId == 19 
        select p; 

var list = from p in listFromSql.AsEnumerable() 
      let trend = CustomFunction(p.ID) 
      where trend > 100 
      select new { p, p.Vendor, trend }; 

更新:回答您列出的問題:

  1. 這是相對簡單的SQL,還等什麼L2SQL生成應該沒問題。您可以使用L2SQL日誌記錄或SQL Profiler來確認SQL是否足夠好。
  2. 請參閱上面的let
  3. Skip()Take()上的IQueryable<>(如上面的listFromSql)將轉換爲適當的SQL,限制通過線路發送的結果集。 Skip()Take()IEnumerable<>只是枚舉序列以獲取請求的結果,但對從SQL返回的完整結果集進行操作。
+0

忘了提及CustomFunction是數據庫中的自定義函數。仍然LINQ語句不會能夠識別它?我使用LINQPAD,它工作正常。 –

+0

我從來沒有使用過自定義函數的L2SQL - 如果它在LINQPAD中有效,我希望它能在任何地方工作。它與'let'一起工作嗎? – dahlbyk

+0

是我使用它是這樣的:(從u用戶加入cat在BusinessCategories上u.UserId等於cat.UserId加入 sub Sub上Cat.SubCategoryId sub等於sub.SubCategoryId sub subCategoryId let trend = CalculateDistance(u.Zipcode,「07306」 ) where sub.CategoryId == 19 && trend <100 select new {u,u.Businesses,trend})。跳過(0)。拿(10) –

1

由於CustomFunction是數據庫中的標量函數,因此LINQ to SQL應該能夠有效地對其進行估算。您可能希望使用LET來提取一次值,但請檢查生成的SQL和查詢執行計劃以查看它是否提供了任何改進,或者SQL Server是否自動在內部進行適當的優化。

var list = (from p in Products 
      join cat in Product_SubCategory_Mapping 
      on p.UserId equals cat.UserId 
      join sub in SubCategories 
      on cat.SubCategoryId equals sub.SubCategoryId 
      let trend = CustomFunction(p.ID) 
      where sub.CategoryId == 19 && trend > 100 
      select new { p, p.Vendor, trend }) 
      .Skip((pageNum - 1) * pageSize) 
      .Take(pageSize); 

如果你的元素之間有關聯,你可能想要使用它們而不是聯接。它不會更改生成的查詢(很多),但可能會更容易維護,因爲連接是由模型中建立的關聯抽象出來的。

var list = (from p in Products 
      from cat in p.Product_SubCategory_Mappings 
      let trend = CustomFunction(p.ID) 
      where cat.SubCategory.CategoryId == 19 && trend > 100 
      select new { Product = p, p.Vendor, trend}) 
      .Skip(pageNum - 1) * pageSize) 
      .Take(pageSize); 
+0

感謝您指出使用關聯。它肯定看起來更清潔。 –