我使用的是OrmLite .NET和SQLServer12.0。我希望选择实体,其中某个整数列(不是主键)具有多个值中的一个,这是我在数组中拥有的。像这样的OrmLite表达式:
q => query.Where(r => myIntegers.Contains(r.TheColumn))
被翻译成
WHERE "TheColumn" IN (1, 2, 3, ...) -- my integers
这对100很好,但对1000来说是超时的。如何通过更大的列表实现同样的效果?我可以以某种方式将数组传递给Server或表参数吗?
发布于 2015-10-23 06:31:27
类似于@JoeTaras的注释,您可以将可接受的值放入子查询中,类似于;
SELECT TheColumn from TheTable T
INNER JOIN (SELECT * from (VALUES(1),(2),(3),(4)) as V1(value)) V
ON T.TheColumn = V.value
发布于 2015-10-23 09:57:22
在OrmLite中,您可以构建所需的原始SQL查询(例如,从@Sam应答)并将其传递给db.Select
方法:
string joinedIds = string.Join("),(", new List<int> {1, 2, 9});
string command =
$"SELECT * from Employee AS E INNER JOIN (SELECT * from (VALUES( {joinedIds} )) as TV(value)) V ON E.Id = V.value";
List<Employee> employers = db.Select<Employee>(command);
发布于 2015-11-17 07:36:18
最后,我为此使用了一个临时表,即:
CREATE TABLE #ParamTempTable (Id BIGINT NOT NULL PRIMARY KEY);
INSERT INTO #ParamTempTable (Id) VALUES ((1), (2), (3));
SELECT *
FROM MyTable
WHERE Id IN (SELECT * FROM #ParamTempTable);
DROP TABLE #ParamTempTable;
只有当我有>1000个值时,我才会这样做,否则我只使用SQL IN (1, 2, 3)
。
要在OrmLite上实现这一点,我必须对SqlServerExpression<T>
进行子类化,并重写VisitStaticArrayMethodCall
和VisitEnumerableMethodCall
,以更改其处理Contains
表达式的方式。这个类分别存储创建和删除临时表的命令,我必须对每个命令分别运行一个SqlCommand
。(不幸的是,CREATE TABLE
不适用于SqlCommand.ExecuteReader
。)因此,这最终是相当复杂的,但它确实有效,并且对调用者来说是透明的。另一个好处是,我可以消除重复的参数,例如,对于o => ids.Contains(o.FromId) || ids.Contains(o.ToId)
,列表ids
只发送一次给server。
https://stackoverflow.com/questions/33303620
复制相似问题