Mam niektóre wyrażenia generujące kod do przekazania jako "where" w czytaniu bazy danych, a ja próbuję trochę przyspieszyć.Zmiana wartości ConstantExpression w istniejącym BinaryExpression
Ten przykład poniżej sprawia, gdzie oświadczenie dopasować PK stole z przekazywane wartości:
private Expression MakeWhereForPK(int id)
{
var paramExp = Expression.Parameter(typeof(Brand),"b");
//Expression to get value from the entity
var leftExp = Expression.Property(paramExp,"ID");
//Expression to state the value to match (from the passed in variable)
var rightExp = Expression.Constant(id,typeof(int));
//Expression to compare the two
var whereExp = Expression.Equal(leftExp,rightExp);
return Expression.Lambda<Func<Brand,bool>>(whereExp,paramExp);
}
Powyższe jest uproszczeniem na pytanie - prawdziwych zawiera kod do podjęcia tabeli na zapytanie i znaleźć jego PK itd. To jest skutecznie robi to samo, co można zrobić w kodzie zwykle:
ctx.Brands.Where(b => b.ID = id);
To działa OK, ale robiąc z badaniem w celu optymalizacji rzeczy trochę Znalazłem jego raczej wolno - wykonanie powyższych 1000000 razy zajmuje około 25 sekund. Lepiej, jeśli pominę ostatnią linię powyżej (ale oczywiście wtedy jest bezużyteczna!), Więc wydaje się, że Expression.Lamba zajmuje około 2/3 czasu, ale reszta też nie jest wspaniała.
Jeśli wszystkie zapytania miałyby się wydarzyć od razu, mógłbym zamienić je na wyrażenie w stylu IN
i wygenerować je raz, ale niestety to nie jest możliwe, więc mam nadzieję, że uda się uratować większość pokolenia powyżej, i po prostu ponownie użyj wygenerowanego wyrażenia, ale przechodząc w innej wartości id
.
Należy zauważyć, że ponieważ zostanie to przekazane do Linq, nie mogę skompilować wyrażenia, aby mieć parametr liczby całkowitej, który można przekazać przy wywołaniu - musi pozostać jako drzewo wyrażeń.
Więc dodaje może być prosta wersja dla celów tego ćwiczenia rozrządu:
Expression<Func<Brand,bool>> savedExp;
private Expression MakeWhereForPKWithCache(int id)
{
if (savedExp == null)
{
savedExp = MakeWhereForPK(id);
}
else
{
var body = (BinaryExpression)savedExp.Body;
var rightExp = (ConstantExpression)body.Right;
//At this point, value is readonly, so is there some otherway to "inject" id,
//and save on compilation?
rightExp.Value = id;
}
return savedExp;
}
Jak mogę ponownie użyć wyrażenia, tylko z inną wartością id?
byłby to pomysł, aby użyć [ 'ParameterExpression'] (http://msdn.microsoft.com/en-us/library/system.linq.expressions.parameterexpression.aspx) zamiast" ConstantExpression "? (Przy okazji, jeśli wydajność jest problemem, po co używać LINQ w ogóle? LINQ handluje wydajnością, ponieważ nie musi uczyć się SQL.) – Andomar
@Andomar: drugi 'ParameterExpression' sprawi, że' Func '. Nie może być używany jako predykat dla 'Where'. –
Dennis