简体   繁体   中英

Create object containing a list using Dynamic Linq Core with Entity Framework 2.0

I have the following two classes:

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;}
}

Using Entity Framework Core 2.0 I have associated these using a one to many relationship. Using Dynamic Linq Core I'm trying to create a query that returns the PartNumber, Description, and the list of all associated Warehouses for a particular part where the only property in the Warehouses list is WarehouseName ideally like this:

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

But I receive this error: "No property or field 'Warehouse' exists in type 'List`1'". If I do something like this it works fine:

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

The problem is that I would like it to be dynamic so that the user can just pass in a list of fields from the Part and Warehouse class that they want to get without having to modify the select to build it for those specific fields.

You'd need to support a subquery on Warehouses . I'll copy the relevant steps listed in this answer :

  1. add the following in 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. Add Select and ToList into IEnumerableSignatures , and a respective condition in 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. Finally, Your query would be:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM