Попытка написать 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);
}
Подробнее здесь: https://stackoverflow.com/questions/787 ... l-variable