Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将LINQ转换为普通Foreach_C#_Linq_Linqkit - Fatal编程技术网

C# 将LINQ转换为普通Foreach

C# 将LINQ转换为普通Foreach,c#,linq,linqkit,C#,Linq,Linqkit,我在我们的一个项目中发现了下面的一段代码。 我被困了两天:-(试图理解聚合和扩展 您能帮助将低于LINQ转换为正常的foreach操作吗 public Expression<Func<Purchase, bool>> forTarget(List<string> idList) { Expression<Func<Purchase, string>> fc = p => p.ClientId; Expression

我在我们的一个项目中发现了下面的一段代码。 我被困了两天:-(试图理解聚合和扩展

您能帮助将低于LINQ转换为正常的foreach操作吗

public Expression<Func<Purchase, bool>> forTarget(List<string> idList)
{
    Expression<Func<Purchase, string>> fc = p => p.ClientId;
    Expression<Func<Purchase, bool>> predicate = m => false;

    return idList.Aggregate(predicate, (p, id) => p.Or(m => fc.Invoke(m) == id), p => p.Expand());
}

internal class Purchase
{
    public int Price { get; set; }
    public string Description { get; set; }
    public string ClientId { get; set; }
}

public class Client
{
    public string Id { get; set; }
}   

该函数迭代项集合,并通过为每个
ClientId
属性值添加
条件来构建谓词

在早期版本的Linq2SQL中,不支持方法
Contains
,因此无法执行如下查询:

IEnumerable<Purchase> purchases = LoadSelectedItems();
var clientIds = purchases.Select( p => p.ClientId ).ToArray();
var results = db.Clients.Where( c => clientIds.Contains( c.Id )); // Did not work.
正如您所看到的,这种语句不是很优雅,当要检查的值集合(即
clientid
)非常大时,就变得不可读,最重要的是,您无法事先知道这些值将是什么来硬编码它们。 因此,为了克服这个问题,解决方案是用一个变量值集合来概括上述谓词。这只需使用以下算法即可完成:

  • 创建一个
    表达式
    ,该表达式返回
    false
    ;如果我们返回
    true
    ,编译器将短路计算(因为我们使用的是
    ),并将为所有项返回true
  • 对于值集合中的每个项,添加带有该项值的
    子句
  • 现在,您的示例可以通过以下方式转换为foreach:

    // start with a predicate returning false
    // this is the seed of the Aggregate method
    Expression<Func<Purchase, bool>> predicate = m => false;
    // Now, iterate the collection and build the full predicate
    foreach( var id in idList)
    {
        // Build the predicate by invoking a function which returns the client id of the 
        // purchase and comparing it with the value of the current id from the idList
        predicate = predicate.Or(item => item.ClientId == id);
    }
    
    //以返回false的谓词开始
    //这是聚合方法的种子
    表达式谓词=m=>false;
    //现在,迭代集合并构建完整谓词
    foreach(idList中的变量id)
    {
    //通过调用一个函数来构建谓词,该函数返回
    //购买并将其与idList中当前id的值进行比较
    谓词=谓词.Or(item=>item.ClientId==id);
    }
    

    希望这有帮助。

    谢谢!这真的很有帮助。请在LinQKit Expand()上找到任何指针吗?@Abhijeet,不幸的是,我没什么可说的了……
    Expand()
    方法尝试“优化”lambda表达式,以便它可以(有效地)转换为SQL查询。
    var results = db.Clients.Where( c => c.Id == 1 || c.Id == 2 || c.Id == 3);
    
    // start with a predicate returning false
    // this is the seed of the Aggregate method
    Expression<Func<Purchase, bool>> predicate = m => false;
    // Now, iterate the collection and build the full predicate
    foreach( var id in idList)
    {
        // Build the predicate by invoking a function which returns the client id of the 
        // purchase and comparing it with the value of the current id from the idList
        predicate = predicate.Or(item => item.ClientId == id);
    }