Biorąc pod uwagę wartość prymitywny age
wiem jak utworzyć wyrażenie takiego:Tworzenie wyrażeń LINQ gdzie parametr równy obiekt
//assuming: age is an int or some other primitive type
employee => employee.Age == age
Robiąc to:
var entityType = typeof(Employee);
var propertyName = "Age";
int age = 30;
var parameter = Expression.Parameter(entityType, "entity");
var lambda = Expression.Lambda(
Expression.Equal(
Expression.Property(parameter, propertyName),
Expression.Constant(age)
)
, parameter);
To działa dobrze z wyjątkiem scenariuszy gdzie właściwość i stała nie są typami pierwotnymi.
Jak skonstruować podobną ekspresję jeśli porównanie jest między obiektami?
EF mogę tylko napisać:
Location location = GetCurrentLocation();
employees = DataContext.Employees.Where(e => e.Location == location);
który działa również, ale gdy próbuję utworzyć ten sam wyraz:
var entityType = typeof(Employee);
var propertyName = "Location";
var location = GetCurrentLocation();
var parameter = Expression.Parameter(entityType, "entity");
var lambda = Expression.Lambda(
Expression.Equal(
Expression.Property(parameter, propertyName),
Expression.Constant(location)
)
, parameter);
pojawia się błąd, który mówi:
Unable to create a constant value of type 'Location'. Only primitive types or enumeration types are supported in this context.
Mój podejrzenie jest takie, że Expression.Constant()
oczekuje tylko typów pierwotnych, więc muszę użyć innej metody fabryki ekspresji. (maype Expression.Object
? - Wiem, że nie istnieje)
Czy istnieje sposób na stworzenie wyrażenia porównującego obiekty? Dlaczego EF potrafi poprawnie zinterpretować, jeśli jest to skompilowane wyrażenie LINQ, ale nie kiedy jest wyrażeniem?
Tak samo na marginesie, użycie Expression.Constant zmusza serwer bazy danych do generowania nowego planu wykonania SQL za każdym razem, gdy wprowadzane są stałe zmiany. Może to mieć duży wpływ na wydajność, zobacz https://stackoverflow.com/questions/34845097/rewriting-a-linq-expression-query-to-enable-caching-sql-execution-plan –