system.linq.dynamic:使用列表(iEnumerable)参数[英] System.Linq.Dynamic : Working with list (IEnumerable) parameters

本文是小编为大家收集整理的关于system.linq.dynamic:使用列表(iEnumerable)参数的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我正在使用 system.linq.dynamic 要编写动态查询,但我无法弄清楚如何将列表(IEnumerable)参数传递给查询: 这是我要实现的目标:

SELECT * FROM People WHERE Role IN ('Employee','Manager')

这是相同查询的LINQ等效:

from person in People where (new string[]{"Employee","Manager"}).Contains(person.Role)

所以我想自己可以使用动态linq编写此查询,为:

People.Where("@0.Contains(Role)","(new string[]{\"Employee\",\"Manager\"})")

此版本不起作用:

People.Where("(new string[]{"Employee","Manager"}).Contains(Role)")

因此,这是一个问题:如何应用动态LINQ库以能够与列表和/或Inumerable参数(例如上述情况)一起使用?

推荐答案

动态LINQ项目本身不支持',我有相同的要求,必须下载源并进行修改以支持它.

我失去了跟上任何Nuget更新的能力,但是该解决方案现在适合我们的需求.我找不到找到这个地方的地方,但这就是我这样做的方式.

编辑dynamic.cs文件,并将以下内容添加到第566行:

interface IEnumerableSignatures
{
    bool Contains(object selector); // Add this
    void Where(bool predicate);
    //...
// Then around line 628 add a new keyword:

static readonly string keywordOuterIt = "outerIt";
static readonly string keywordIt = "It";
//...
// above ParameterExpression It; add
ParameterExpression outerIt;

// In ParseIdentifier add
if (value == (object)keywordOuterIt) return ParseOuterIt();

//Then add that method
Expression ParseOuterIt()
{
    if (outerIt == null)
        throw ParseError(Res.NoItInScope);
    NextToken();
    return outerIt;
}

// In ParseAggreggate, add:
outerIt = it;

if (signature.Name == "Min" || signature.Name == "Max")
{
    typeArgs = new Type[] { elementType, args[0].Type };
}
else
{
    typeArgs = new Type[] { elementType };
}
if (args.Length == 0)
{
    args = new Expression[] { instance };
}
else
{   
    // add this section
    if (signature.Name == "Contains")
        args = new Expression[] { instance, args[0] };
    else
    {
        args = new Expression[] { instance, Expression.Lambda(args[0], innerIt) };
    }
}

// In CreateKeyWords()

d.Add(keywordOuterIt, keywordOuterIt); // Add this

我不知道我们是否可以在这里上传源,但是我一直在维护自己的Dynamic.cs副本,并尝试将其与Nuget上的版本保持最新.如果您愿意,我会很乐意上传.我只是不记得我从哪里得到的,因为在动态linq上搜索包含错误的结果 - 指向字符串包含,而不是iEnumerable.contains.

其他推荐答案

动态LINQ不支持Contains默认情况下.

您可以以旧的方式进行:

var roles = new[] { "Employee", "Manager" };
var predicate = new StringBuilder();
for (var i = 0; i < roles.Length; i++)
{
    string role = roles[i];
    predicate.AppendFormat("Role = @{0}", i);
    if (i < roles.Length) predicate.Append(" OR ");
}

People.Where(predicate.ToString(), role.Cast<object>().ToArray());

以下问题是: link .在提到的问题中,还有其他替代品.

其他推荐答案

我知道的旧问题,但是我花了一个时间来修复.使用最新的动态linq在这里为其他人引用它: https://github.com/github.com/zzzprojects/sysemprojects/sysystem.linq.dynamic.核心/问题/314

so:

List<string> ids = new List<string>(){ 1, 2, 3 };
List<string> stringIds = new List<string>(){ "test", "find", "something" };

var queryResults = context.someEntity.AsNoTracking();
queryResults = queryResults.Where("intColName in @0", ids);
queryResults = queryResults.Where("stringColName in @0", strings);

var results = await queryResults.ToListAsync();

此生成SQL喜欢:

select cols where intColName in (1, 2, 3) AND stringColName IN (N'test', N'find', N'something')

本文地址:https://www.itbaoku.cn/post/1556943.html

问题描述

I am using System.Linq.Dynamic to be able to write dynamic queries but I could not figure it out that how I can pass list (IEnumerable) parameters to a query : Here's what I want to achieve :

SELECT * FROM People WHERE Role IN ('Employee','Manager')

And here's the Linq equivalent of the same query :

from person in People where (new string[]{"Employee","Manager"}).Contains(person.Role)

So I thought to myself that I could write this query using dynamic Linq as :

People.Where("@0.Contains(Role)","(new string[]{\"Employee\",\"Manager\"})")

This version is not working neither:

People.Where("(new string[]{"Employee","Manager"}).Contains(Role)")

So here's the question : How can I apply Dynamic Linq Library to be able to work with list and or IEnumerable parameters such as the above scenario ?

推荐答案

The Dynamic linq project does not support 'contains' natively, I had the same requirement and had to download the source and modify it to support it.

I have lost the ability to keep up with any nuget updates, but the solution now works for our needs. I can't find where I found this, but this is how I did it.

Edit the dynamic.cs file and add the following to around line 566:

interface IEnumerableSignatures
{
    bool Contains(object selector); // Add this
    void Where(bool predicate);
    //...
// Then around line 628 add a new keyword:

static readonly string keywordOuterIt = "outerIt";
static readonly string keywordIt = "It";
//...
// above ParameterExpression It; add
ParameterExpression outerIt;

// In ParseIdentifier add
if (value == (object)keywordOuterIt) return ParseOuterIt();

//Then add that method
Expression ParseOuterIt()
{
    if (outerIt == null)
        throw ParseError(Res.NoItInScope);
    NextToken();
    return outerIt;
}

// In ParseAggreggate, add:
outerIt = it;

if (signature.Name == "Min" || signature.Name == "Max")
{
    typeArgs = new Type[] { elementType, args[0].Type };
}
else
{
    typeArgs = new Type[] { elementType };
}
if (args.Length == 0)
{
    args = new Expression[] { instance };
}
else
{   
    // add this section
    if (signature.Name == "Contains")
        args = new Expression[] { instance, args[0] };
    else
    {
        args = new Expression[] { instance, Expression.Lambda(args[0], innerIt) };
    }
}

// In CreateKeyWords()

d.Add(keywordOuterIt, keywordOuterIt); // Add this

I don't know if we can upload source here, but I've been maintaining my own copy of Dynamic.cs, and trying to keep it up to date with the version on nuget. I'll be happy to upload it if you want. I just don't remember where I got all this, because searching for contains on Dynamic linq mostly yields the wrong results - pointing to string contains, not IEnumerable.contains.

其他推荐答案

Dynamic LINQ doesn't support Contains by default.

You can do it in old way:

var roles = new[] { "Employee", "Manager" };
var predicate = new StringBuilder();
for (var i = 0; i < roles.Length; i++)
{
    string role = roles[i];
    predicate.AppendFormat("Role = @{0}", i);
    if (i < roles.Length) predicate.Append(" OR ");
}

People.Where(predicate.ToString(), role.Cast<object>().ToArray());

Here is question about that: link. In mentioned question there is also other replacements.

其他推荐答案

Old question I know, but took me an age to fix. Referencing it here for others using the latest Dynamic-linq: https://github.com/zzzprojects/System.Linq.Dynamic.Core/issues/314

So:

List<string> ids = new List<string>(){ 1, 2, 3 };
List<string> stringIds = new List<string>(){ "test", "find", "something" };

var queryResults = context.someEntity.AsNoTracking();
queryResults = queryResults.Where("intColName in @0", ids);
queryResults = queryResults.Where("stringColName in @0", strings);

var results = await queryResults.ToListAsync();

This generate sql like:

select cols where intColName in (1, 2, 3) AND stringColName IN (N'test', N'find', N'something')