在EntityFramework EntitySql中使用"option(maxrecursion 0)"

IPV*_*rde 7 c# sql-server entity-framework common-table-expression entity-sql

我有执行recrusive基于输入,这是一个csv字符串IDS与CTE选择一个SQLServer功能.

不幸的是我不能使用"选项(MAXRECURSION 0)"我的函数中,必须在执行功能时使用.问题是我无法找到如何在EntityFramework的EntitySql中使用此选项.

考虑到我的函数被调用MyRecursiveFunction,这里有一些代码片段:

public virtual IQueryable<MyFunctionReturnType> ExecuteMyFunction(IObjectContextAdapter objContextAdapter, string csvIds)
{
    var idsParam = new ObjectParameter("idsParam", csvIds);

    // This is the original one, that works, but has no "option(maxrecursion 0)"
    return objContextAdapter.CreateQuery<MyFunctionReturnType>("[MyRecursiveFunction](@idsParam)", idsParam);

    // gives me an error of incorrect syntax near "option"
    return objContextAdapter.CreateQuery<MyFunctionReturnType>("select VALUE tblAlias from [MyRecursiveFunction](@idsParam) as tblAlias OPTION(MAXRECURSION 0)", idsParam);

    // Also gives me syntax error:
    return objContextAdapter.CreateQuery<MyFunctionReturnType>("MyRecursiveFunction(@idsParam) option(maxrecursion 0)", idsParam);
}
Run Code Online (Sandbox Code Playgroud)

任何人都知道如何使用option(maxrecursion 0)entitySql?

我知道我可以使用"ExecuteStoreQuery"来执行我想要的任何sql查询,但我确实需要一个IQueryable,因为"ExecuteMyFunction"的返回将在实现之前与另一个IQueryable连接.

请节省您的时间和不建议调用ExecuteStoreQuery沿AsQueryable....我真的不想兑现对整个结果集,因为我会兑现只有10结果分页.

这是我的TVF的代表:

-- Consider that I have the given table for executing this function.
-- This table has a foreign key to itself, as the data represents a tree, like an organization chart
CREATE TABLE MyTable
(
    Id INT,
    ParentId INT, -- FK to 'MyTable'.'Id',
    Name VARCHAR(400)
)

-- Here is my function definition:
CREATE FUNCTION MyRecursiveFunction (@idsParam VARCHAR(MAX))
RETURNS TABLE
AS
RETURN
(
    -- create a cte for recursively getting the data
    with myCte (id, parentId) as
    (
        SELECT tbl.Id, tbl.ParentId FROM MyTable AS tbl
        -- This function just transform the varchar into a table of "Value"
        INNER JOIN [dbo].[SplitTextIntoTableOfInt](@idsParam, ',') AS ids ON a.ParentId = ids.Value

        UNION ALL

        SELECT a.Id, a.ParentId FROM myCte AS parent
        INNER JOIN MyTable tbl ON tbl.ParentId = parent.Id
    )
    SELECT * FROM myCte -- I can't use 'option(maxrecursion 0)' in here
)
Run Code Online (Sandbox Code Playgroud)

Jot*_*aBe 5

您唯一能做的就是使用EF 拦截并在运行它之前将该选项添加到 EF 生成的 SQL。

为此,您需要实现IDbCommandInterceptorinterface,并使用它DbInterception.Add(new YousCommandInterceptor());来注册您的拦截器。

您的拦截器可以在将查询发送到服务器之前添加该选项。SQL 查询在所选方法的命令参数中可用(您应该拦截ReaderExecuted(DbCommand,?DbCommandInterceptionContext<DbDataReader>)


Dou*_*oug 1

OPTION(MAXRECURSION 0)特定于 SQL Server 语法,我认为 EntitySql 永远不会支持这种特定语法。这将使抽象与底层数据存储过于耦合,并且难以支持其他数据库服务器。

如果您达到了某些递归限制,也许检查您的设计是个好主意,因为放弃限制会使您的问题变得更糟。