我正在通过将它们转换为编译查询来加速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"语句编译查询?我究竟做错了什么?
调用存储过程,并使用以下方法传入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)
走