LINQ:将SQL WITH子句转换为LINQ和实体框架

本文关键字:LINQ 实体 框架 转换 子句 SQL WITH | 更新日期: 2023-09-27 17:50:20

我有一个使用实体框架的应用程序。我想添加一个按类别分组的产品列表树视图。我有一个旧的SQL查询,将抓取所有的产品和类别,并将它们安排到父节点和子节点。我正试图将其翻译成使用EF的LINQ。但是SQL有一个WITH子查询,我不熟悉使用。我试过使用Linqer和LinqPad来解决这个问题,但它们在WITH子句上卡住了,我不确定如何修复它。这种事情在LINQ中可能吗?

下面是查询:

declare @id int
set @id=0
WITH ChildIDs(id,parentid,type,ChildLevel) AS 
(
SELECT id,parentid,type,0 AS ChildLevel
FROM dbo.brooks_product 
WHERE id = @id
UNION ALL
SELECT e.id,e.parentid,e.type,ChildLevel + 1
FROM dbo.brooks_product AS e
    INNER JOIN ChildIDs AS d
    ON e.parentid = d.id 
   WHERE  showitem='yes' AND tribflag=1
)
SELECT ID,parentid,type,ChildLevel 
FROM ChildIDs
WHERE type in('product','productchild','productgroup','menu')
ORDER BY ChildLevel, type
OPTION (MAXRECURSION 10);

当我运行查询时,我得到的数据看起来像这样(几千行,在这里截断):

ID.....parentid.....type.....ChildLevel
35429..0............menu.....1
49205..0............menu.....1
49206..49205........menu.....2
169999.49206........product..3
160531.169999.......productchild..4

LINQ:将SQL WITH子句转换为LINQ和实体框架

WITH块是一个公共表表达式,在本例中用于创建递归查询。

在Linq中将非常困难,因为Linq不能很好地使用递归。如果您需要一个结果集中的所有数据,那么使用存储过程会更容易。另一种选择是在c#中进行递归(不是在Linq中,而是递归函数)并进行多次往返。性能将不会那么好,但如果结果集很小,它可能不会产生太大的差异(并且您将获得更好的对象模型)。

你也许可以使用LINQ to Entities来解决这个问题,但它不是微不足道的,我怀疑它将非常耗时。

在这种情况下,您可能更愿意构建一个SQL视图或表值函数来返回您正在寻找的结果。然后将视图或表值函数导入到EF模型中,您可以使用LINQ直接从中提取数据。

在LINQ中查询View和查询一个表没有什么不同。

要在LINQ中从表值函数中获取数据,您需要在函数名之后传递函数的参数,如下所示:

var query = from tvf in _db.MyTableValuedFunction(parameters)
            select tvf;

编辑

正如@thepirat000所建议的,表值函数支持在版本5之前的实体框架版本中不可用。为了使用这个功能,EF必须运行在。net 4.5或更高版本。

在一天结束的时候,我无法让这个工作。我最终动态地编写了一个SQL查询,并将其直接发送到数据库。它工作得很好,我不依赖于任何直接的用户输入,所以没有SQL注入的机会。但它看起来太老派了!对于我的程序的其余部分,我使用EF和LINQ。

谢谢你的回复!