LINQ to SQL 查询优化

发布于 2024-12-01 17:59:19 字数 1121 浏览 0 评论 0原文

主要从事java工作,对LINQ很陌生,所以我需要一些关于此查询性能的建议。我有3个表,

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. 对于分页,Skip 和 take 表现良好吗?

Have been working mainly on java and new to LINQ so I need some suggestion regarding performance of this query .I have 3 tables

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

I want to select all products from product table along with its Vendors for any given subcategory .Should following query work fine ? Or it needs any optimization ?

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);

I will be creating a custom class that will match result of query .

  1. Is creating a view/Stored procedure a better scenario in case like this ?
  2. Can CustomFunction(p.ID)>100 be named so function is not called twice ? Its a custom function in Database.
  3. For paging will Skip and take perform well ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时光匆匆的小流年 2024-12-08 17:59:19

您的方向是正确的,但 LINQ to SQL 无法理解 CustomFunction(),因此您需要先使用 AsEnumerable() 切换到 LINQ to Objects可以调用它。您还可以使用 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. IQueryable 上的 Skip()Take() (如上面的 listFromSql)将转换为适当的 SQL,限制通过线路发送的结果集。 IEnumerable<> 上的 Skip()Take() 只是枚举序列以获取请求的结果,但对完整结果进行操作从 SQL 返回的集合。

You're on the right track, but LINQ to SQL won't understand CustomFunction() so you'll need to switch to LINQ to Objects with AsEnumerable() before you can call it. You can also use let to capture the result of CustomFunction() once for use elsewhere in the query:

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 };

Update: To answer your listed questions:

  1. This is relatively straightforward SQL, so what L2SQL generates should be fine. You can use L2SQL logging or SQL Profiler to confirm that the SQL is good enough.
  2. See let above.
  3. Skip() and Take() on an IQueryable<> (like listFromSql above) will translate into the appropriate SQL, limiting the result set sent across the wire. Skip() and Take() on an IEnumerable<> just enumerate the sequence to get the requested results, but operate on the full result set returned from SQL.
短暂陪伴 2024-12-08 17:59:19

由于 CustomFunction 是数据库中的 ScalarFunction,因此 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);

Since CustomFunction is a ScalarFunction in the database, LINQ to SQL should be able to evaulate it effectively. You may want to use LET to pull the value once, but check the generated SQL and the Query Execution Plan to see if it offers any improvement or if SQL Server automatically makes the appropriate optimizations internally.

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); 

If there are associations between your elements, you may want to use them rather than joins. It doesn't change the generated query (much), but may be a bit more maintainable since the joins are abstracted out by the associations established in the model.

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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文