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

c# dynamic-linq entity-framework-core list

Question

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.

1
0
4/13/2018 6:47:45 PM

Popular Answer

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
            )");
    }
    
0
8/22/2019 8:16:46 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow