Я предполагаю, что это EF Core 2.x. Я бы порекомендовал избегать этого типа выражения запроса, так как автоматическая оценка запросов c была изменена в EF Core 3, чтобы люди не полагались на него. Я подозреваю, что существуют также крайние случаи с ошибками, например, то, с чем вы столкнулись, когда выполняемая клиентская оценка думает, что сущность отсоединена.
С точки зрения производительности, полагаться на ленивую загрузку будет вредно в долгосрочной перспективе. Один из вариантов, который вы могли бы рассмотреть для централизации правил, таких как Status, состоял бы в том, чтобы отразить их как выражения / функции в домене. Это работает с булевыми выражениями, поэтому ваша проверка «Статус» должна быть организована так, чтобы утверждать определенную комбинацию:
public class Activity {
...
public virtual ICollection<Approver> ApprovalStatus {get; set;}
public static Func<Activity, bool> IsApproved() {
return (Activity a) => (a.ApprovalStatus.All(x => ...)
&& !a.ApprovalStatus.Any(x => ...);
public static Func<Activity, bool> IsRejected() {
return (Activity a) => (!a.ApprovalStatus.All(x => ...)
|| a.ApprovalStatus.Any(x => ...);
}
}
, затем при потреблении:
applicationDbContext.Activities.Where(Activity.IsApproved());
Вы все еще можете иметь неотображенный свойство для отложенной оценки в коде:
[NotMapped]
public bool? Status
{
get
{
if(IsApproved().Invoke(this))
return true;
if(IsRejected().Invoke(this))
return false;
return null;
}
}
Предостережение этого подхода состоит в том, что с вашими предложениями Where
вы не можете легко отрицать или составлять дополнительные условия ИЛИ. Например, следующее не работает:
applicationDbContext.Activities.Where(!Activity.IsApproved());
Мне пришлось немного покопаться, чтобы посмотреть, есть ли способ получить его, чтобы выражение могло быть примерно таким:
applicationDbContext.Activities.Where(x => x.IsApproved());
с помощью метода расширения stati c чтобы вернуть выражение, но я не смог заставить что-либо работать. Там может быть какая-то черная магия Func / Expression c, которая сработает и на самом деле сделает это через Linq2Entity, но даже если так, я ожидаю, что это будет выглядеть довольно отвратительно.
Лучший вариант IMO - это написать выражения как вам нужно с доступными свойствами. Т.е.:
applicationDbContext.Activities.Where(a => (a.ApprovalStatus.All(x => ...)
&& !a.ApprovalStatus.Any(x => ...)
// ...
);
Возможно, было бы неплохо иметь возможность повторно использовать выражения, но приведенный выше вариант был бы наиболее гибким и наиболее эффективным.