LINQ防爆pression返回属性值? [英] LINQ Expression to return Property value?

查看:136
本文介绍了LINQ防爆pression返回属性值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建一个泛型函数来帮我选择数以千计的使用LINQ从本地列表的SQL记录。 SQL服务器(2005年至少)限制查询到2100年参数,我想比选择更多的记录。

下面将是一个很好的例子用法:

  VAR some_product_numbers = INT新[] {1,2,3 ... 9999};Products.SelectByParameterList(some_product_numbers,P => p.ProductNumber);

下面是我的(非工作)执行:

 公共静态的IEnumerable< T> SelectByParameterList< T,属性类型>(表< T>的项目,IEnumerable的<属性类型> PARAMETERLIST,防爆pression<&Func键LT; T,属性类型>>属性),其中T:类
{
    VAR组= PARAMETERLIST
    。选择((参数index)=>
    新
    {
    组ID =指数/ 2000,每个请求// 2000参数
    参数
    }
    )
    .GroupBy(X => x.GroupID)
    .AsEnumerable();    VAR的结果=组
    。选择(G =>新建{集团= G,参数= g.Select(X => x.Parameter)})
    .SelectMany(G =>
    / *这部分出现故障悲惨的遭遇* /
    items.Where(项目=> g.Parameters.Contains(property.Compile()(项目)))
    );    返回结果;
}

我看到很多使用前pressions建设predicates的例子。在这种情况下,我只想要执行的委托返回当前ProductNumber的价值。或者说,我要翻译成SQL查询本(正常工作非通用的形式)。

我知道,编译防爆pression只是把我带回到了起点(在委托传递为Func键),但我不能确定如何将参数传递给未编译EX pression。

感谢您的帮助!

**编辑:让我进一步明确:

下面是什么,我想概括工作的例子:

  VAR local_refill_ids = Refills.Select(R = GT; r.Id)。取(20).ToArray();VAR组= local_refill_ids
。选择((参数index)=>

{
组ID =指数/ 5,每个请求// 5参数
参数
}

.GroupBy(X => x.GroupID)
.AsEnumerable();VAR的结果=组
。选择(G =>新建{集团= G,参数= g.Select(X => x.Parameter)})
.SelectMany(G =>
Refills.Where(R => g.Parameters.Contains(r.Id))

.ToArray()
;

结果在这个SQL code:

  SELECT [T0]。[ID],... [T0]。[版本]
FROM [加注] AS [T0]
WHERE [T0]。[ID] IN(@ P0,P1 @,@ P2,P3 @,@ P4)...该查询4次以上(20/5 = 4)


解决方案

最简单的方式做到这一点:使用 LINQKit (免费,非限制性许可证)

code的工作版本:

 公共静态的IEnumerable< T> SelectByParameterList< T,属性类型>(此表< T>项目的IEnumerable<属性类型> PARAMETERLIST,防爆pression< Func键< T,属性类型>> propertySelector,INT块大小),其中T:类
{
    VAR组= PARAMETERLIST
    。选择((参数index)=>
    新
    {
    组ID =索引/块大小,//每个请求参数#
    参数
    }
    )
    .GroupBy(X => x.GroupID)
    .AsEnumerable();    VAR选择= LinqKit.Linq.Expr(propertySelector);    VAR的结果=组
    。选择(G =>新建{集团= G,参数= g.Select(X => x.Parameter)})
    .SelectMany(G =>
    / * AsExpandable()扩展方法需要LinqKit DLL * /
    items.AsExpandable(),其中(项目=> g.Parameters.Contains(selector.Invoke(项目)))。
    );    返回结果;
}

实例:

 的Guid [] = local_refill_ids Refills.Select(R = GT; r.Id)。取(20).ToArray();    IEnumerable的<笔芯>结果= Refills.SelectByParameterList(local_refill_ids,R => r.Id,10); //运行每10个参数2 SQL查询

再次感谢您的帮助!

I'm trying to create a generic function to help me select thousands of records using LINQ to SQL from a local list. SQL Server (2005 at least) limits queries to 2100 parameters and I'd like to select more records than that.

Here would be a good example usage:

var some_product_numbers = new int[] { 1,2,3 ... 9999 };

Products.SelectByParameterList(some_product_numbers, p => p.ProductNumber);

Here is my (non-working) implementation:

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;
}

I have seen plenty of examples of building predicates using expressions. In this case I only want to execute the delegate to return the value of the current ProductNumber. Or rather, I want to translate this into the SQL query (it works fine in non-generic form).

I know that compiling the Expression just takes me back to square one (passing in the delegate as Func) but I'm unsure of how to pass a parameter to an "uncompiled" expression.

Thanks for your help!

** EDIT: Let me clarify further:

Here is a working example of what I want to generalize:

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()
;

Results in this SQL code:

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)

解决方案

Easiest way to do this: Use LINQKit (Free, non-restrictive license)

Working version of code:

public static IEnumerable<T> SelectByParameterList<T, PropertyType>(this Table<T> items, IEnumerable<PropertyType> parameterList, Expression<Func<T, PropertyType>> propertySelector, int blockSize) where T : class
{
    var groups = parameterList
    	.Select((Parameter, index) =>
    		new
    		{
    			GroupID = index / blockSize, //# of parameters per request
    			Parameter
    		}
    	)
    	.GroupBy(x => x.GroupID)
    	.AsEnumerable();

    var selector = LinqKit.Linq.Expr(propertySelector);

    var results = groups
    .Select(g => new { Group = g, Parameters = g.Select(x => x.Parameter) } )
    .SelectMany(g => 
    	/* AsExpandable() extension method requires LinqKit DLL */
    	items.AsExpandable().Where(item => g.Parameters.Contains(selector.Invoke(item)))
    );

    return results;
}

Example usage:

    Guid[] local_refill_ids = Refills.Select(r => r.Id).Take(20).ToArray();

    IEnumerable<Refill> results = Refills.SelectByParameterList(local_refill_ids, r => r.Id, 10); //runs 2 SQL queries with 10 parameters each

Thanks again for all your help!

这篇关于LINQ防爆pression返回属性值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆