Ho le seguenti due classi:
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;}
}
Usando Entity Framework Core 2.0 ho associato questi usando una relazione uno a molti. Utilizzando Dynamic Linq Core sto cercando di creare una query che restituisca PartNumber, Description e l'elenco di tutti i Warehouse associati per una particolare parte in cui l'unica proprietà nell'elenco Warehouse è idealmente simile a 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();
Ma ricevo questo errore: "Non esiste alcuna proprietà o campo" Magazzino "nel tipo" Elenco "1" ". Se faccio qualcosa del genere, funziona bene:
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();
Il problema è che vorrei che fosse dinamico in modo che l'utente potesse semplicemente passare un elenco di campi della classe Part and Warehouse che voleva ottenere senza dover modificare la selezione per crearlo per quei campi specifici.
Dovresti supportare una sottoquery su Warehouses
. Copierò i passaggi pertinenti elencati in questa risposta :
aggiungere quanto segue 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
...
}
Aggiungi Select
and ToList
in IEnumerableSignatures
e una rispettiva condizione 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")
...
}
Infine, la tua query sarebbe:
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
)");
}