Перехват и изменение основного запроса EntityFramework на основе типа объекта - PullRequest
0 голосов
/ 04 мая 2020

Можно ли изменить запрос EntityFramework Core во время выполнения, основываясь на типах запрашиваемой сущности?

Например, вот упрощенная версия некоторых таблиц:

Department (id, name)
Manager (id, deptid, name)
Employee (id, deptid, name, role)
Payslip (id, employeeid, amount)

Таким образом, менеджер должен иметь возможность видеть всех сотрудников в своем отделе, а также их платежные ведомости, но ничего в любом другом отделе. Сотрудник должен видеть только свои собственные платежные ведомости.

Очевидно, я мог бы каждый раз писать что-то вроде Context.Employees.Where(x => x.deptId == manager.deptid), мне нужно это видеть. Но это довольно упрощенная версия того, чего я надеюсь достичь, я надеюсь встроить средства защиты для разработчиков, чтобы помочь им не пропустить объединение или ограничение и в конечном итоге показать неправильные элементы. В идеале это уменьшило бы необходимость кодировать вещи по-разному для менеджеров, пользователей и т. Д. c (я уверен, что будут случаи, но многие базовые функции c могут быть упрощены)

Я добавил интерфейсы с ключевыми объектами, такими как

public interface IDepartmentFilterable
{
    Guid DepartmentId { get; set; }
}

Поэтому что-то вроде Employee должно быть Employee : IDepartmentFilterable и содержать этот идентификатор.

Возможно ли во время запроса перехватить запрос, например

Context.Employees().Where(x => x.Name.StartsWith('Fred'));

Итак, я мог бы go

//Foreach EntityBeingQueried
// If(entity is IDepartmentFilterable)
//   Query.WhereConditions.Add { entity.DepartmentId == user.DepartmentId }

Поэтому в любое время, когда выполняется запрос с присоединенным пользовательским контекстом, я мог автоматически ограничивать результаты на основе самих сущностей и интерфейсов, которых они придерживаются .

В нашем наборе данных много реляционных данных, поэтому мне не хотелось кодировать множество отдельных вызовов репозитория с такими вещами, как GetEmployeePayslipsForUser и GetEmployeesPayslipsForManagerForMonth, я надеялся, что если Я мог бы выполнить фильтрацию на уровне контекста базы данных (и, возможно, позволить разработчику сознательно переопределить ее вручную), это могло бы реально ускорить и защитить нашу разработку.

* 102 8 * В некотором роде похоже на то, как я вижу измененные сущности, когда переопределяю SaveChanges (), например
var modifiedEntities = ChangeTracker.Entries()
        .Where(p => p.State == EntityState.Modified).ToList();
    var now = DateTime.UtcNow;

Мне бы очень хотелось что-то похожее для 'Запрошенных записей'

РЕДАКТИРОВАТЬ:

Я думаю, что я делаю некоторые успехи ... этот метод позволил бы мне изменить входной запрос, это просто, где поместить его во время запроса, я не знаю, справится ли он с соединениями или включает et c .. но это может и не быть проблемой.

public virtual void Update(Expression<Func<TEntity, bool>> where)
{
    var objects = _dbContext.Set<TEntity>().Where(where).Where(e => !e.Deleted).AsEnumerable();
    foreach (var item in objects)
    {
        Update(item);
    }
}
...