我正在尝试创建一个通用函数,帮助我使用LINQ to SQL从本地列表中选择数千条记录。SQL Server(至少是2005版)限制查询到2100个参数,而我希望选择更多的记录。
以下是一个很好的使用示例:
var some_product_numbers = new int[] { 1,2,3 ... 9999 };
Products.SelectByParameterList(some_product_numbers, p => p.ProductNumber);
以下是我的(不可用的)实现:
public static IEnumerable<T> SelectByParameterList<T, PropertyType>(Table<T> items,
IEnumerable<PropertyType> parameterList, Expression<Func<T, PropertyType>> property) where T : class
{
var groups = parameterList
.Select((Parameter, index) =>
new
{
GroupID = index / 2000, //2000 parameters per request
Parameter
}
)
.GroupBy(x => x.GroupID)
.AsEnumerable();
var results = groups
.Select(g => new { Group = g, Parameters = g.Select(x => x.Parameter) } )
.SelectMany(g =>
/* THIS PART FAILS MISERABLY */
items.Where(item => g.Parameters.Contains(property.Compile()(item)))
);
return results;
}
我看到了很多使用表达式构建谓词的例子。在这种情况下,我只想执行委托以返回当前ProductNumber的值。或者说,我想将其转换为SQL查询(非泛型形式可以正常工作)。
我知道编译Expression只会让我回到原点(将委托作为Func传递),但我不确定如何向“未编译”的表达式传递参数。
感谢您的帮助!
****编辑:** 让我进一步澄清:
以下是我想要概括的工作示例:
var local_refill_ids = Refills.Select(r => r.Id).Take(20).ToArray();
var groups = local_refill_ids
.Select((Parameter, index) =>
new
{
GroupID = index / 5, //5 parameters per request
Parameter
}
)
.GroupBy(x => x.GroupID)
.AsEnumerable();
var results = groups
.Select(g => new { Group = g, Parameters = g.Select(x => x.Parameter) } )
.SelectMany(g =>
Refills.Where(r => g.Parameters.Contains(r.Id))
)
.ToArray()
;
这段SQL代码的结果:
SELECT [t0].[Id], ... [t0].[Version]
FROM [Refill] AS [t0]
WHERE [t0].[Id] IN (@p0, @p1, @p2, @p3, @p4)
... That query 4 more times (20 / 5 = 4)
queryable.Where(o => values.Contains(o.propertyToTest))
这种情况,通过将其替换为queryable.InRange(o => o.propertyToTest, blockSize, values)
(如果我理解正确的话)。但我在关注类似于2100个参数限制的溢出问题,例如queryable.Where(o => !values.Contains(o.propertyToTest))
。我正在尝试修改InRange()函数以获得NotInRange()等效函数,并且我不确定如何进行布尔否定。我的想法是在foreach (T record in source.Where(lambda))
的一行里进行? - Matt Sachyield return
。 - Code Maverick