【问题标题】:Create object containing a list using Dynamic Linq Core with Entity Framework 2.0使用 Dynamic Linq Core 和 Entity Framework 2.0 创建包含列表的对象
【发布时间】:2019-08-22 16:16:46
【问题描述】:

我有以下两个类:

public Part {
    public string PartNumber {get; set;}
    public string Description {get; set;}
    public List<Warehouse> Warehouses {get; set;}
}

public Warehouse {
    public string PartNumber {get; set;}
    public string WarehouseName {get; set;}
    public int Quantity {get; set;}
    public int ReorderPoint {get; set;}
}

使用 Entity Framework Core 2.0 我使用一对多关系将这些关联起来。使用 Dynamic Linq Core 我正在尝试创建一个查询,该查询返回 PartNumber、Description 以及特定部件的所有关联仓库列表,其中仓库列表中的唯一属性是 WarehouseName,理想情况下如下所示:

List<string> fields = new List<string> {"PartNumber", "Description", "Warehouses.WarehouseName"};
var _dataSet = dbContext.Parts.Include(x => x.Warehouses);
var data = _dataSet.Where("PartNumber = \"Part1234\"").Select("new (" + String.Join(",", fields) + ")").ToDynamicArray();

但我收到此错误:“'List`1' 类型中不存在属性或字段 'Warehouse'”。如果我做这样的事情它工作正常:

var data = _dataSet.Where("PartNumber = \"Part1234\"").Select(x => new Part
{
    PartNumber = x.PartNumber,
    Description = x.Description,
    Warehouses = x.Warehouses.Select(y => new Warehouse { Warehouse = y.Warehouse }).ToList()
}).Single();

问题是我希望它是动态的,这样用户就可以从 Part 和 Warehouse 类中传入他们想要获取的字段列表,而无需修改选择来为这些特定字段构建它.

【问题讨论】:

  • 在您的fields:Warehouses[0].WarehouseName 中尝试此作为测试。如果这样可行,那么您还需要为其他索引添加索引。
  • @CodingYoshi 这将返回一个有效的数据对象,但 WarehouseName 只是一个字段,它不是一个列表。我如何添加索引以返回所有仓库(可能有 0 到 100)?

标签: c# list entity-framework-core dynamic-linq


【解决方案1】:

您需要支持Warehouses 上的子查询。我将复制this answer中列出的相关步骤:

  1. ParseAggregate中添加以下内容:

    Expression ParseAggregate(Expression instance, Type elementType, string methodName, int errorPos)
    {
       // Change starts here
       var originalIt = it;
       var originalOuterIt = outerIt;
       // Change ends here
    
       outerIt = it;
       ParameterExpression innerIt = Expression.Parameter(elementType, elementType.Name);
       it = innerIt;
       Expression[] args = ParseArgumentList();
    
       // Change starts here
       it = originalIt;
       outerIt = originalOuterIt;
       // Change ends here
    
       ...
    }
    
  2. SelectToList 添加到IEnumerableSignatures 中,并在ParseAggregate 中添加相应的条件:

    interface IEnumerableSignatures
    {
      ...
      void Select(object selector);
      void ToList();
      ...
    }
    
    Expression ParseAggregate(Expression instance, Type elementType, string methodName, int errorPos)
    {
       ...
       if (signature.Name == "Min" || 
           signature.Name == "Max" || 
           signature.Name == "Select")
       ...
    }
    
  3. 最后,您的查询是:

    static void Main()
    {
        // example data
        var warehouses = new List<Warehouse>
        {
            new Warehouse { WarehouseName = "NY1", Quantity = 10 },
            new Warehouse { WarehouseName = "NY2", Quantity = 100 }
        };
        var parts = new List<Part> 
        { 
             new Part { PartNumber = "1", Description = "Hammer", Warehouses = warehouses } 
        };
        // query
        var result =
            parts
            .Select(@"new ( 
               PartNumber,
               Description,
               Warehouses.Select(WarehouseName).ToList() as WarehouseNames
            )");
    }
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-28
    • 1970-01-01
    • 1970-01-01
    • 2018-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多