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
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。
谢谢你的回复!