Запрос рекурсивной таблицы ядра ядра Entity Framework занимает много времени - PullRequest
0 голосов
/ 12 марта 2019

У меня есть объект / таблица организации, одна организация может быть родительской (рекурсивной) другой в моем приложении.Я сделал вид дерева организации, как показано ниже (только пример), который все работает отлично.У меня около 3000 записей организации.

enter image description here

Однако запрос, который создает ядро, занимает некоторое незначительное время, примерно 6000 мс (проверено с помощью SE miniprofiler и sql Event Profiler) ,

Здесь сущность организации, ее контекстная конфигурация и рекурсивный (включая дочерние сущности) метод get соответственно.

public class OrganizationEntity : BaseEntity
{
    public int TkId { get; set; }
    public string Text { get; set; }
    public string TextEn { get; set; }
    public int? TkTopId { get; set; }
    public int LevelCode { get; set; }
    public string CountryCode { get; set; }
    public string City { get; set; }

    public Guid? ParentOrganizationId { get; set; }
    public virtual OrganizationEntity ParentOrganization { get; set; }

    public Guid? ManagerId { get; set; }
    public virtual EmployeeEntity Manager { get; set; }

    public virtual ICollection<OrganizationEntity> ChildOrganizations { get; set; }
}

private void ConfigureOrganization(EntityTypeBuilder<OrganizationEntity> builder)
{
    builder.ToTable("Organization");
    builder.HasMany(o => o.ChildOrganizations).WithOne(o => o.ParentOrganization).HasForeignKey(o => o.ParentOrganizationId);
}


public List<OrganizationEntity> GetAll()
{
    var organizations = _organizationRepository.Get(includeProperties: "ChildOrganizations").ToList();
    var parentOrganizations = organizations.Where(x => x.ParentOrganization == null).ToList();

    return parentOrganizations;
}

Строка

_organizationRepository.Get(includeProperties:"ChildOrganizations").ToList();

производит следующий SQL-запрос.

Исходный запрос

SELECT [e].[Id], [e].[City], [e].[CountryCode], [e].[CreatedBy], [e].[CreatedOn], [e].[IsDeleted], [e].[LevelCode], [e].[ManagerId], [e].[ModifiedBy], [e].[ModifiedOn], [e].[OrderId], [e].[ParentOrganizationId], [e].[Text], [e].[TextEn], [e].[TkId], [e].[TkTopId]
FROM [Organization] AS [e]
WHERE [e].[IsDeleted] = 0
ORDER BY [e].[Id]

Включить запрос

SELECT [e0].[Id], [e0].[City], [e0].[CountryCode], [e0].[CreatedBy], [e0].[CreatedOn], [e0].[IsDeleted], [e0].[LevelCode], [e0].[ManagerId], [e0].[ModifiedBy], [e0].[ModifiedOn], [e0].[OrderId], [e0].[ParentOrganizationId], [e0].[Text], [e0].[TextEn], [e0].[TkId], [e0].[TkTopId]
FROM [Organization] AS [e0]
INNER JOIN (
    SELECT [e1].[Id]
    FROM [Organization] AS [e1]
    WHERE [e1].[IsDeleted] = 0
) AS [t] ON [e0].[ParentOrganizationId] = [t].[Id]
WHERE [e0].[IsDeleted] = 0
ORDER BY [t].[Id]

Что ж, когда я выполняю эти запросы в студии управления SQL Server, оба вместе занимают всего около 350 мс.Что может быть причиной этой задержки?

Редактировать, код репозитория

public IEnumerable<T> Get(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, string includeProperties = null, bool asNoTracking = false, int? skip = null, int? take = null)
           => GetQueryable(filter, orderBy, includeProperties, asNoTracking, skip, take);

protected virtual IQueryable<T> GetQueryable(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null,
                                                    string includeProperties = null,
                                                    bool asNoTracking = false,
                                                    int? skip = null,
                                                    int? take = null)
{
    includeProperties = includeProperties ?? string.Empty;
    IQueryable<T> query = _dbContext.Set<T>();

    if (filter != null)
    {
        query = query.Where(filter);
    }

    foreach (var includeProperty in includeProperties.Split
        (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
    {
        query = query.Include(includeProperty);
    }

    if (orderBy != null)
    {
        query = orderBy(query);
    }

    if (skip.HasValue)
    {
        query = query.Skip(skip.Value);
    }

    if (take.HasValue)
    {
        query = query.Take(take.Value);
    }

    if (asNoTracking)
    {
        query = query.AsNoTracking();
    }

    return query;
}

1 Ответ

0 голосов
/ 13 марта 2019

Включение AsNoTracking() для запроса привело к тому, что длительность выполнения запроса достигла нормального уровня (так же, как на сервере sql).

_organizationRepository.Get(includeProperties:"ChildOrganizations", asNoTracking: true).ToList();

...