使用带有Entity Framework 2.0的Dynamic Linq Core创建包含列表的对象

时间:2018-04-13 18:47:45

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

我有以下两个类:

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以及特定部分的所有相关仓库的列表,其中Warehouses列表中唯一的属性是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();

但是我收到了这个错误:&#34;没有财产或字段&#39;仓库&#39;存在于类型&#39; List`1&#39;&#34;中。如果我做这样的事情就可以了:

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类的字段列表,而无需修改select以为这些特定字段构建它

1 个答案:

答案 0 :(得分:0)

您需要在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. Select中添加ToListIEnumerableSignatures,并在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
            )");
    }