Отправная точка
Код: Выделить всё
var contractSubjectKey = new ContractSubjectKey(subjectId, rank);
insurance = context.Set()
.FirstOrDefault(i => i.Key.ContractSubjectKey == contractSubjectKey);
Код: Выделить всё
i => i.Key.ContractSubjectKey.Id == contractSubjectKey.Id
Думаю, я разобрался с левой стороной операции. Начальная левая часть BinaryExpression — это MemberExpression.
Код: Выделить всё
var left = Expression.Property(memberExpression, "Id");
В случае, если я использую для правой стороны ConstantExpression
Код: Выделить всё
var right = Expression.Constant(1, typeof(int));
Код: Выделить всё
i.Key.ContractSubjectKey.Id == 1
У меня проблема с правой стороной. Правая часть — это выражение. Значения параметров я не могу найти нигде в исходном 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
Мобильная версия