Способ всегда фильтровать результаты запроса с помощью Entity Framework Core - PullRequest
0 голосов
/ 08 ноября 2019

Я использую OrgID на всех моих моделях в приложении ASP.NET, используя EF для разделения базы данных. Я делаю это так, чтобы база данных могла совместно использоваться несколькими пользователями, обеспечивая при этом доступность только данных их организации.

Это вынуждает меня записывать эту OrgID при каждой вставке и фильтровать каждый вызовЯ делаю в базу данных.

Так, например, я запрашиваю у текущего пользователя OrgID и вставляю это в Update методы моих контроллеров, например:

store.OrgID = await _userManager.GetUserAsync(User).OrgID;
_context.Update(store);
await _context.SaveChangesAsync();

Затем, когда я хочучтобы перечислить объекты, мне снова нужно отфильтровать по OrgID:

var orgID = await _userManager.GetUserAsync(User).OrgID;
var stores = await _context.Stores.Where(s => s.OrgID == orgID).ToListAsync();

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

Любые предложения будут с благодарностью.

Ответы [ 3 ]

1 голос
/ 08 ноября 2019

Проверка Глобальные фильтры запросов .

Глобальные фильтры запросов - это предикаты запросов LINQ (логическое выражение, обычно передаваемое оператору запросов LINQ Where), применяемые к типам сущностей в модели метаданных (обычно в OnModelCreating). Такие фильтры автоматически применяются к любым запросам LINQ, связанным с этими типами объектов, включая типы объектов, на которые косвенно ссылаются, например, с помощью ссылок на свойства «Включить» или «Прямая навигация».

0 голосов
/ 08 ноября 2019

Создайте интерфейс с OrgID:

public interface IOrgID
{
    public int OrgID { get; set; }
}

Все ваши модели должны реализовывать этот интерфейс, например:

public class ApplicationUser : IdentityUser, IOrgID
{
    public int OrgID { get; set; }

    //...
}

public class Stores : IOrgID
{
    public int OrgID { get; set; }

    //...
}

Использовать универсальный репозиторий и создавать методы CRUD с учетом OrgID изв данный момент залогинен пользователь:

public class MyRepo
    {
        private readonly ApplicationDbContext _context;
        private readonly IHttpContextAccessor _accessor;
        private readonly int _orgID;

        public MyRepo(ApplicationDbContext context, IHttpContextAccessor accessor)
        {
            _context = context;
            _accessor = accessor;

            var userId = _accessor.HttpContext.User.FindFirstValue(ClaimTypes.NameIdentifier);
            _orgID = _context.Users.Find(userId).OrgID;
        }

        public async Task<T> GetAsync<T>(Expression<Func<T, bool>> whereExp)
            where T : class, IOrgId
        {
            return await _context.Set<T>().Where(x => x.OrgId == _orgID).FirstOrDefaultAsync(whereExp);
        }

        public async Task<bool> Create<T>(T entitiy)
            where T : class, IOrgId
        {
            _context.Set<T>().Add(entitiy);
            return await _context.SaveChangesAsync() > 0;
        }

        public async Task<bool> UpdateAsync<T>(T entity)
            where T : class, IOrgId
        {
            _context.Entry<T>(entity).State = EntityState.Modified;
            return await _context.SaveChangesAsync() > 0;
        }

        public async Task<IEnumerable<T>> ListAsync<T>(Expression<Func<T, bool>> whereExp)
            where T : class, IOrgId
        {
            return await _context.Set<T>().AsNoTracking().Where(x => x.OrgId == _orgID).Where(whereExp).ToListAsync();
        }

        public async Task<bool> DeleteAync<T>(T entity)
            where T : class, IOrgId
        {
            _context.Entry<T>(entity).State = EntityState.Deleted;
            return await _context.SaveChangesAsync() > 0;
        }
    }
0 голосов
/ 08 ноября 2019

Что люди делают в этом случае, так это создают класс, обертывающий DbContext и раскрывающий методы, которые имеют смысл для их бизнес-логики. В вашем случае вы можете создать UserRepository / StoreRepository классы, где для методов поиска требуется origID paramamter

public class StoreRepository {

    private ApplicationDBContext _context

    StoreRepository(ApplicationDBContext context){
     _context = context
    }

    public Task<Ilist<Store>> GetStores(int origID){
       return _context.Stores.Where(s => s.OrgID == orgID).ToListAsync();
    } 
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...