Свойство доступа посетителя выражения для параметра, представляющего локальную переменнуюC#

Место общения программистов C#
Ответить
Anonymous
 Свойство доступа посетителя выражения для параметра, представляющего локальную переменную

Сообщение Anonymous »

Попытка написать ExpressionVisitor, который переписывал бы запрос
Отправная точка

Код: Выделить всё

var contractSubjectKey = new ContractSubjectKey(subjectId, rank);

insurance = context.Set()
.FirstOrDefault(i => i.Key.ContractSubjectKey == contractSubjectKey);

После ожидаемой перезаписи

Код: Выделить всё

i => i.Key.ContractSubjectKey.Id == contractSubjectKey.Id
Я пытаюсь переписать BinaryExpression, чтобы оно само сравнивало свойства.
Думаю, я разобрался с левой стороной операции. Начальная левая часть BinaryExpression — это MemberExpression.

Код: Выделить всё

var left = Expression.Property(memberExpression, "Id");
Поэтому я просто получаю доступ к самому свойству.
В случае, если я использую для правой стороны ConstantExpression

Код: Выделить всё

var right = Expression.Constant(1, typeof(int));
чтобы результирующая операция выглядела так:

Код: Выделить всё

i.Key.ContractSubjectKey.Id == 1
он ​​без проблем транслируется в SQL и извлекает данные.
У меня проблема с правой стороной. Правая часть — это выражение. Значения параметров я не могу найти нигде в исходном Expression или QueryExpressionEventData (при работе с IQueryExpressionInterceptor). Не уверен, что понимаю это до конца. Он представляет собой локальную переменную, вычисляет во время трансляции что-то близкое к константе?

В любом случае, если я попробую PropertyExpression

Код: Выделить всё

var right = Expression.Property(parameterExpression, "Id");
Кажется, у меня получилось правильное выражение, но во время перевода оно выходит из строя
`Выражение Linq.... не удалось перевести

System.InvalidOperationException: выражение LINQ 'DbSet()
.Where(i => EF.Property(EF.Property(i, "Key"), "ContractSubjectKey").Id == __contractSubjectKey_0.Id)' не удалось перевести. Либо перепишите запрос в форме, которую можно перевести, либо явно переключитесь на клиентскую оценку, вставив вызов AsEnumerable, AsAsyncEnumerable, ToList или ToListAsync.

Значит, проблема где-то в значении оценки идентификатора локальной переменной?
Перепробовал много вещей... не буду тратить здесь место.< /p>
Еще один дополнительный фрагмент контекста

Код: Выделить всё

public record ContractSubjectKey(int Id, int Rank);

//insurance.Key.ContractSubjectKey is actually ContractSubjectKeyInsurance which inherits from ContractSubjectKey
public record ContractSubjectKeyInsurance : ContractSubjectKey
{
public ContractSubjectKeyInsurance(int Id, int Rank) : base(Id, Rank)
{

}
public ContractSubjectKeyInsurance(int Id, int Rank, int InsuranceKeyId) : base(Id, Rank)
{
_insuranceKeyId = InsuranceKeyId;
}

private int _insuranceKeyId;
}

public record InsuranceKey(int Id, ContractSubjectKey ContractSubjectKey)
{
this.Id = Id;
_contractSubjectId = ContractSubjectKey.Id;
_contractSubjectRank = ContractSubjectKey.Rank;
this.ContractSubjectKey =
new ContractSubjectKeyInsurance(ContractSubjectKey.Id,  ContractSubjectKey.Rank, Id);
}

РЕДАКТИРОВАТЬ
Итак, проблема не в переписывании самого выражения. Я работаю с EF Core. Я хочу подключить IQueryExpressionInterceptor, который будет изменять такое выражение для каждого требуемого запроса. Проблема здесь в том, что есть IQueryTranslationPreprocessor, который извлекает и кэширует параметры. Таким образом, начальный запрос представляет собой выражение доступа к членам/константному выражению, и вы можете переписать его, используя только дополнительный доступ к свойствам; как только запрос достигнет IQueryExpressionInterceptor, это станет невозможно. Ссылка ниже на заявку, которая, я думаю, может описать ситуацию.

https://github.com/dotnet/efcore/issues/30208
Возможное решение включает собственный IQueryTranslationPreprocessor/Postprocessor. Постпроцессор должен иметь доступ к значению параметра. Препроцессор позволяет настроить первоначальный запрос или кэширование параметров. Разработчики EF Core предупреждают о необходимости настройки препроцессора, поскольку это может привести к снижению производительности.

Подробнее здесь: https://stackoverflow.com/questions/787 ... l-variable
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»