Ich habe ein kleines Problem mit der Erstellung dynamischer Ausdrucksbaum für Suchlogik. Das Erstellen eines Ausdrucksbaums für Entitätseigenschaft funktioniert gut, aber ich habe keine Ahnung, wie man einen Ausdruck hinzufügt, der nach Kindobjekteigenschaften filtern wird.Filtern, aber Eigentum und Kind Entitätseigenschaft
Hier ist meine Aufgabe Einheit ist:
public class Task: Entity
{
public TaskType Type { get; set; }
public TaskPriority Priority { get; set; }
public int ProjectId { get; set; }
public Project Project { get; set; }
}
Und hier Projektgesellschaft ist:
public class Project: Entity
{
public int CustomerId { get; set; }
public Customer Customer { get; set; }
}
und Logik für die Entwicklung dynamischer Ausdruck:
public Func<TaskItem, bool> Build(IList<Filter> filters)
{
ParameterExpression param = Expression.Parameter(typeof(TaskItem), "task");
List<Filter> priorityFilter = FilterFilters(filters, "Priority");
List<Filter> typeFilter = FilterFilters(filters, "Type");
List<Filter> customerFilter = FilterFilters(filters, "CustomerId");
Expression expression = null;
// BuildExpression is a method which simply creates expression which is using Tasks properties (like Type or Priority)
expression = BuildExpression(param, priorityFilter, expression);
expression = BuildExpression(param, typeFilter, expression);
// This part need's to be reworked
ParameterExpression projectParam = Expression.Parameter(typeof(Project), "project");
Expression projectCustomerExpression = Expression.Equal(Expression.PropertyOrField(projectParam, "CustomerId"), Expression.Constant(customerFilter[0].Value));
Expression customerExpression = Expression.Equal(Expression.PropertyOrField(param, "Project"), projectCustomerExpression);
Expression finall = expression != null ? Expression.AndAlso(expression, projectCustomerExpression) : projectCustomerExpression;
// End of filtering by CutomerId
return Expression.Lambda<Func<TaskItem, bool>>(finall, param).Compile();
}
Ich habe keine Ahnung, wie nach CustomerId filtern. Der Teil über dem Code, der als This part need's to be reworked
markiert ist, ist wahrscheinlich falsch oder zumindest der letzte Teil davon. Die Idee besteht darin, existierende Ausdrücke (diese durch BuildExpression
erstellte Methode) um einen Ausdruck zu erweitern, der nach CustomerId gefiltert wird.
Ich habe schon etwas Zeit verloren, versuche es selbst und suche nach Antworten, aber ohne Ergebnisse.
Irgendwelche Hilfe?
Danke - Sie haben meinen Tag gerettet! Aber mit einem solchen Ausdruck bekomme ich "Objektreferenz nicht auf eine Instanz eines Objekts gesetzt", wenn ich ToList() so lade: 'Context.Tasks.Where (searchCondition) .ToList()' (Suchbedingung enthält das Ausdruck es ist 'IQueryable'). Der Stack-Trace: 'at lambda_method (Closure, Task), bei System.Linq.Enumerable.WhereEnumerableIterator1.ToList(), bei System.Linq.Enumerable.ToList [TSource] (IEnumerable1 Quelle) '. Irgendwelche Ideen? –
@DawidRutkowski Wahrscheinlich ist 'Project'' null'. Wenn Sie "IQueryable' füllen möchten, sollten Sie die Methodensignatur ändern, um 'Expression >' zurückzugeben und 'Compile()' zu entfernen. Derzeit, selbst wenn Ihre Quelle 'IQueryable ' ist, ruft der Compiler 'Where' Methode auf' IEnumerable '. –
@DawidRutkowski Obwohl ich nicht sicher bin, aber eine mögliche Ursache wäre, wie von @ IvanStoev hingewiesen. Wenn Sie '.Compile' in' searchCondition' verwenden, müssen Sie das nicht tun, es sei denn, Sie möchten das verzögerte Laden vermeiden. Stattdessen können Sie einfach die 'searchCondition' direkt auf' IQueryable' Daten anwenden und dann 'ToList' zum Aufzählen. Wenn das nicht funktioniert, können Sie als Hack versuchen, den Navigationseigenschaftenpfad (mit Ausnahme der letzten Eigenschaft im Pfad; d. H. Die tatsächliche Eigenschaft des einfachen Typs) einzubeziehen, um eine Verknüpfung zu erzwingen. –