c# - 系统.Linq.Dynamic.Core : How do I make a select many correctly?

标签 c# .net linq dynamic-linq

我是 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
                }
            }
        }
    }
}

我想选择带有EquipmentsPacks,但是在选定的Equipments中我需要只有 带有 Id=2 的通用设备。(结果应包含带有设备列表的包列表)。

我已经试过了:

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

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

非常感谢

最佳答案

Dynamic LINQ 的最新版本似乎是项目 here , 与文档 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. 在接受适当参数的任何类上编写一个静态方法

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

关于c# - 系统.Linq.Dynamic.Core : How do I make a select many correctly?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40567289/

相关文章:

c# - Console.Read() 和 Console.ReadLine() 问题

c# - 如何检查对象是否是sql to linq类型

c# - "Primitive types"与 "built-in value types"

c# - 我如何控制我的图像并在我的 ListView 中使用它创建动画?

c# - 当我设置 IIS 池的 LoadUserProfile 时到底发生了什么?

.net - 如何将 .NET 登录到 QRADAR

c# - Linq 查询合并列表中的不同项目

c# - 获取文本文件中的最后两行

c# - ActiViz .NET 左键释放事件 : Where did i click

c# - 静态方法如何调用虚方法?