System.Linq.Dynamic.Core :如何正确地使 select 多?

System.Linq.Dynamic.Core : How do I make a select many correctly?

我是 System.Linq.Dynamic.Core 的新手。我有这个:

假设我们有:

Packs = new List<Pack>
{
    new Pack()
    {
        IdAtSource="Pack1",
        Equipments= new List<Equipment>()
        {
            new Equipment
            {
                Id=1,
                GenericEquipment = new GenericEquipment()
                {
                    Id=7
                }
            }
        }
    },
    new Pack()
    {
        IdAtSource="Pack2",
        Equipments= new List<Equipment>()
        {
            new Equipment
            {
                Id=2,
                GenericEquipment = new GenericEquipment()
                {
                    Id=1
                }
            },
            new Equipment
            {
                Id=2,
                GenericEquipment = new GenericEquipment()
                {
                    Id=2
                }
            }
        }
    }
}

我想 select PacksEquipments,但是在 selected Equipments 我需要 只有 通用设备 Id=2 的那个。(结果应该包含带有设备列表的包列表)。

我试过这个:

querable.Where("Packs.Equipments.Select((GenericEquipment.Id)=1)");

但我觉得我没有达到目标。还有关于如何使用这个库的文档页面吗?

非常感谢

这些应该有效:

var equipments= from pack in Packs where pack.Equipments.Any() select pack.Equipments;

var secondEquipments = from pac in equipments where       
pac.GenericEquipment.Id == 2 select pac;
//I could use one variable instead of 2 but that would look a little bit complex

Msdn Link(抱歉,我在移动端,所以无法重命名): https://msdn.microsoft.com/en-us/library/bb397927.aspx

Dynamic LINQ 的最新版本似乎是项目 here, with the documentation here


通常,您需要动态 LINQ 而不是标准 LINQ 的唯一原因是类型在编译时未知

如果您在编译时知道查询将针对 List<Pack>,您可以使用标准 LINQ,如以下代码所示(注意这会修改 Pack 的原始实例) :

var usefulPacks = Packs.Select(pack => {
    pack.Equipments = pack.Equipments.Where(equipment => 
        equipment.GenericEquipment.Id == 1
    ).ToList(); 
}).Where(pack => pack.Equipments.Any()).ToList();

如果您需要不修改原始实例的代码,此代码会创建原始实例的副本:

var usefulPacks = Packs.Select(pack => {
    return new Pack() {
        IDAtSource = pack.IDAtSource,
        Equipments = pack.Equipments.Where(equipment => 
            equipment.GenericEquipment.Id == 1
        ).ToList(); 
    };
}).Where(pack => pack.Equipments.Any()).ToList();

请注意,这不是使用 .SelectMany.SelectMany 用于从嵌套枚举创建单个枚举;这里最终列表中的每个 Pack 对应于原始列表中的 Pack


动态 LINQ 不支持修改或初始化属性作为表达式的一部分:

The expression language permits getting (but not setting) the value of any reachable public field, property, or indexer.

因此 Equipments 属性 无法更改/初始化为仅包含符合条件的 Equipment 实例。

为了设置Equipments,你有两个选择:

  1. Pack 添加一个构造函数,它接受适当的参数
  2. 在任何 class 上编写一个静态方法,它接受适当的参数

添加构造函数到Pack

您可以使用适当的参数向 Pack 添加构造函数,设置 Equipments:

Pack(int IDAtSource, IEnumerable<Equipment> equipments) {
    this.IDAtSource = IDAtSource;
    this.Equipments = equipments.ToList();
}

那么您可以使用以下内容:

IQueryable qry = Packs.AsQueryable();
qry = qry
    .Select("Pack(IDAtSource, Equipments.Where(GenericEquipment.ID=1))")
    .Where("Equipments.Any");

定义静态方法

public static class MyPackMethods {
    public static Pack Create(int IDAtSource, IEnumerable<Equipment> equipments) {
        return new Pack() {
            IDAtSource = IDAtSource,
            Equipments = equipments.ToList()
        };
    }
}

并调用:

IQueryable qry = Packs.AsQueryable();
qry = qry
    .Select("MyPackMethods.Create(IDAtSource, Equipments.Where(GenericEquipment.ID=1))")
    .Where("Equipments.Any");