2011-08-29 91 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

感谢您指出使用关联。它肯定看起来更清洁。 –