使用Contains的Linq编译查询(与SQLs IN语句一样)

Mic*_*oie 5 linq linq-to-sql

我正在通过将它们转换为编译查询来加速Linq到SQL查询在Web应用程序中的过程,我遇到了转换一个非常简单的语句的问题.

我想编译一个简单的语句,它使用以下参数从数据库中获取有效的员工:

TestParams myParams = new TestParams
{
    ValidEmps = new int[] { 1, 2, 3 }
};
Run Code Online (Sandbox Code Playgroud)

这是工作查询:

IQueryable<Employees> MySelectedEmps =
    from emps in db.Employees
    where myParams.ValidEmps.Contains(emps.EmployeeID)
    select emps;
Run Code Online (Sandbox Code Playgroud)

这是我尝试编译它:

private static Func<MyDataContext, TestParams, IQueryable<Employee>> myCompiledQuery =
    CompiledQuery.Compile((MyDataContext db, TestParams myParams) =>
        from emps in db.Employees
        where myParams.ValidEmps.Contains(emps.EmployeeID)
        select emps);
Run Code Online (Sandbox Code Playgroud)

这个语句有编译和构建,但是当我运行它时,我收到以下运行时错误:

类型'System.Int32 []'不支持比较运算符

我也尝试使用相同的错误消息传递List和IEnumerable.

我也尝试用.Any(valemp => valemp == emps.EmployeeID)语句替换.Contains语句但我仍然得到相同的错误.

是否可以使用等效的SQL"IN"语句编译查询?我究竟做错了什么?

KM.*_*KM. 5

调用存储过程,并使用以下方法传入CVS值列表:

在使用我的函数之前,需要设置一个"帮助程序"表,每个数据库只需执行一次:

CREATE TABLE Numbers
(Number int  NOT NULL,
    CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number ASC)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
DECLARE @x int
SET @x=0
WHILE @x<8000
BEGIN
    SET @x=@x+1
    INSERT INTO Numbers VALUES (@x)
END
Run Code Online (Sandbox Code Playgroud)

使用此函数来分割您的字符串,它不会循环并且非常快:

CREATE FUNCTION [dbo].[FN_ListToTable]
(
     @SplitOn              char(1)              --REQUIRED, the character to split the @List string on
    ,@List                 varchar(8000)        --REQUIRED, the list to split apart
)
RETURNS
@ParsedList table
(
    ListValue varchar(500)
)
AS
BEGIN

/**
Takes the given @List string and splits it apart based on the given @SplitOn character.
A table is returned, one row per split item, with a column name "ListValue".
This function workes for fixed or variable lenght items.
Empty and null items will not be included in the results set.


Returns a table, one row per item in the list, with a column name "ListValue"

EXAMPLE:
----------
SELECT * FROM dbo.FN_ListToTable(',','1,12,123,1234,54321,6,A,*,|||,,,,B')

    returns:
        ListValue  
        -----------
        1
        12
        123
        1234
        54321
        6
        A
        *
        |||
        B

        (10 row(s) affected)

**/



----------------
--SINGLE QUERY-- --this will not return empty rows
----------------
INSERT INTO @ParsedList
        (ListValue)
    SELECT
        ListValue
        FROM (SELECT
                  LTRIM(RTRIM(SUBSTRING(List2, number+1, CHARINDEX(@SplitOn, List2, number+1)-number - 1))) AS ListValue
                  FROM (
                           SELECT @SplitOn + @List + @SplitOn AS List2
                       ) AS dt
                      INNER JOIN Numbers n ON n.Number < LEN(dt.List2)
                  WHERE SUBSTRING(List2, number, 1) = @SplitOn
             ) dt2
        WHERE ListValue IS NOT NULL AND ListValue!=''



RETURN

END --Function FN_ListToTable
Run Code Online (Sandbox Code Playgroud)

您可以将此函数用作连接中的表:

SELECT
    Col1, COl2, Col3...
    FROM  YourTable
        INNER JOIN FN_ListToTable(',',@YourString) s ON  YourTable.ID = s.ListValue
Run Code Online (Sandbox Code Playgroud)

所以对于Linq,创建一个存储过程:

创建程序YourProcedure(

 @param1  int
,@param2  varchar(8000) --csv list is here
Run Code Online (Sandbox Code Playgroud)

)as

SELECT
    Col1, COl2, Col3...
    FROM YourTable
        INNER JOIN FN_ListToTable(',',@param2  ) s ON  YourTable.ID = s.ListValue
    WHERE Col1=@param1
Run Code Online (Sandbox Code Playgroud)