В настоящее время я работаю с решением .net core (vnext), которое использует ядро linq и entity framework.Linq Expression Tree - Concatenate Массив значений
Мы используем Microsoft.Linq.Translations для хранения вычисляемых определений столбцов в виде лямбда-выражения, чтобы затем их можно было вводить в наши инструкции, когда это необходимо. Пример вычисленного определения заключается в следующем:
private static readonly CompiledExpression<Model, string> fullNameExpression =
aTranslation<Model>.Expression(e => e.FullName, e => $"{e.FirstName} {e.LastName} ({e.Code})");
и потреблять/выполнить его:
var list = context.Set<Model>().Where(e => e.FullName.Contains("Bob")).WithTranslations();
Это все «Технически,» отлично работает .... как в правильном результате получает связанное назад для моделей сущностей, однако работа выполняется в памяти вместо того, чтобы строить запрос в SQL. Это проблема, так как в наших моделях данных могут появиться миллионы строк данных, и сделать это в памяти будет непросто.
Это то, что мы в конечном итоге на данный момент:
.Lambda #Lambda1<System.Func`2[Model,System.Boolean]>(Model $e) {
.Call (.Call System.String.Format(
"{0} {1} ({2})",
$e.FirstName,
$e.LastName,
$e.Code)).Contains("Bob")
}
Как я уже сказал, это работает, но результаты в задаче выполняется в памяти, а не SQL. Запрос получает генерируется что-то вроде:
SELECT FirstName, LastName, Code FROM Model
Так что, если я изменил вычисляемое определение следующим образом (обратите внимание, я просто строю строку вручную вместо использования string.format:
private static readonly CompiledExpression<Model, string> fullNameExpression =
aTranslation<Model>.Expression(e => e.FullName, e => e.FirstName + " " + e.LastName + "(" + e.Code + ")");
Это производит лямбда-выражение, как следующее:
.Lambda #Lambda1<System.Func`2[Model,System.Boolean]>(Model $e) {
.Call ($e.FirstName + " " + $e.LastName + " (" + $e.Code + ")").Contains("Bob")}
Это будет работать и правильно построить запрос SQL из
.SELECT * FROM Model WHERE (FirstName + ' ' + LastName + '(' + Code + ')') LIKE '%bob%'
Таким образом, чтобы изменить способ вычисления или определения вычисленных определений, я пытаюсь написать слой, который берет определение, написанное с использованием выражения linq в строковом формате, и заменяет это выражение на второй тип (например, строку конкатенация)
Я начал писать этот слой перехватывает выражение форматирования строки и построение списка/массива элемента и постоянных выражений, т.е. ПгвЬЫата, «», LastName, «(» и т.д ....
Я попробовал u петь струну Concat подхода обернув через значение и оценку левое и правое выражение, но это заканчивается тем, что что-то другое, что не работает:
.Call System.String.Concat(
.Call System.String.Concat(
.Call System.String.Concat(
.Call System.String.Concat(
$e.FirstName,
" "),
$e.LastName),
" ("),
$e.Code)
Теперь я застрял о том, как преобразовать этот список выражений для получения такого рода выражений:
.Lambda #Lambda1<System.Func`2[Model,System.Boolean]>(Model $e) {
.Call ($e.FirstName + " " + $e.LastName + " (" + $e.Code + ")").Contains("Bob")}
Любая помощь была бы принята с благодарностью.
----------------- Edit -------------
Кодекс пытался до сих пор.Для краткости я оставил строение переменной «concatArgs». Это просто список, содержащий типы MemberExpression и ConstantExpression.
Expression expr = GenerateStringConcat(concatArgs[0], concatArgs[1]);
for(int i = 2; i < concatArgs.Count; i++)
expr = GenerateStringConcat(expr, concatArgs[i]);
и вызываемый метод является показать ниже
private Expression GenerateStringConcat(Expression left, Expression right) {
return Expression.Call(
null,
typeof(string).GetMethod("Concat", new[] { typeof(object), typeof(object) }),
new[] { left, right });
}
Написать выражение вручную в запросе, который работает. Затем декомпилируйте сборку (или используйте Roslyn онлайн), чтобы увидеть, какое дерево выражений генерируется компилятором C#. Это шаблон, который вы можете использовать. – usr
Отправьте код, который вы попробовали, чтобы мы могли его отрегулировать. –