Как реализовать фильтры данных Entity Framework Core? - PullRequest
0 голосов
/ 04 октября 2018

В моем приложении ASP.NET Zero я хочу настроить фильтры данных по значению CompanyId.Поэтому я прочитал документы здесь и информацию, предоставленную на этом форуме поддержки thread .

В моем проекте EF Core я внес следующие изменения.

public override void PreInitialize()
{
    if (!SkipDbContextRegistration)
    {
        // ...

        Configuration.UnitOfWork.RegisterFilter("CompanyFilter", false);
    }
}

Затем я следовал шаблону, используемому для IMustHaveTenant фильтра данных, и применил приведенные ниже изменения в моем классе контекста БД:

protected int? CurrentCompanyId = null;
protected bool IsCompanyFilterEnabled => CurrentCompanyId != null && CurrentUnitOfWorkProvider?.Current?.IsFilterEnabled("CompanyFilter") == true;    

protected override bool ShouldFilterEntity<TEntity>(IMutableEntityType entityType)
{
    if (typeof(IHasCompany).IsAssignableFrom(typeof(TEntity)))
    {
        return true;
    }
    return false;
}

protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>()
{
    Expression<Func<TEntity, bool>> expression = null;

    if (typeof(IHasCompany).IsAssignableFrom(typeof(TEntity)))
    {
        Expression<Func<TEntity, bool>> companyFilter = e => ((IHasCompany)e).CompanyId == CurrentCompanyId || (((IHasCompany)e).CompanyId == CurrentCompanyId) == IsCompanyFilterEnabled;
        expression = expression == null ? companyFilter : CombineExpressions(expression, companyFilter);
    }
    return base.CreateFilterExpression<TEntity>();
}

Затем в своем методе обслуживания приложения, где я хочу применитьФильтр, я добавил код ниже.

public async Task<PagedResultDto<EmployeeListDto>> GetEmployees(GetEmployeeInput input)
{
    using (CurrentUnitOfWork.EnableFilter("CompanyFilter"))
    {
        using (CurrentUnitOfWork.SetFilterParameter("CompanyFilter", "CompanyId", GetCurrentUserCompany()))
        {
            // ...
        }
    }
}

В классе контекста БД, если в строке ниже значение I hard code a CompanyId, фильтр работает простоотлично .

protected int? CurrentCompanyId = 123;

Если честно, я не совсем понимаю код, который используется в методе CreateFilterExpression в классе контекста БД.Я позаимствовал это прямо из кода репо ABP GitHub для фильтра IMustHaveTenant.

Я изменил модал пользователя «Мои настройки» для пользователя ABP, добавив CompanyId.Это позволяет каждому пользователю быть назначенным в компанию, и поэтому приложение должно ограничить все данные по компании для этого пользователя.

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

Вопросы:

  • Нужно ли устанавливать значение этой компании в классе контекста БД?
  • Если да, то как мне вызвать службу приложения или метод репозитория, чтобы получить CompanyId в этом классе контекста БД?

Обновление: Я добавил предложенный кодАароном и его до сих пор не работает.Я тестирую с идентификатором пользователя, которому назначена компания 1.Тем не менее, когда данные загружаются, они все равно показывают их компании 1 и 2.

App service showing filter (line 71) has been set.

Debug cmd window showing company filter is set.

Когда строка 77 выполняет и выполняет вызов GetAll в хранилище, он все равно показывает пользователю все компании.

Обновление 6 октября: Новый код работает ,но только когда пользователю назначен идентификатор компании.Когда пользователю не назначена компания, выдается ошибка, показанная на рисунке ниже.DB context error

1 Ответ

0 голосов
/ 05 октября 2018
  • Нужно ли устанавливать значение этой компании в классе контекста Db?
  • Если да, то как мне вызвать метод приложения или метод хранилища, чтобы получить идентификатор компании в этомКласс контекста БД?

Нет.Реализуйте метод получения в своем классе DbContext:

// using Abp.Collections.Extensions;

// protected int? CurrentCompanyId = null;
protected int? CurrentCompanyId => GetCurrentCompanyIdOrNull();

protected virtual int? GetCurrentCompanyIdOrNull()
{
    if (CurrentUnitOfWorkProvider != null &&
        CurrentUnitOfWorkProvider.Current != null)
    {
        return CurrentUnitOfWorkProvider.Current
            .Filters.FirstOrDefault(f => f.FilterName == "CompanyFilter")?
            .FilterParameters.GetOrDefault("CompanyId") as int?;
    }

    return null;
}

Возвратите expression в своем методе CreateFilterExpression:

protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>()
{
    // Expression<Func<TEntity, bool>> expression = null;
    var expression = base.CreateFilterExpression<TEntity>();

    if (typeof(IHasCompany).IsAssignableFrom(typeof(TEntity)))
    {
        Expression<Func<TEntity, bool>> companyFilter = e => ((IHasCompany)e).CompanyId == CurrentCompanyId || (((IHasCompany)e).CompanyId == CurrentCompanyId) == IsCompanyFilterEnabled;
        expression = expression == null ? companyFilter : CombineExpressions(expression, companyFilter);
    }

    // return base.CreateFilterExpression<TEntity>();
    return expression;
}

Аналогичный вопрос: Внедрите фильтр OrganizationUnit вASP.NET Core

...