3

I'm using EF Core for my project. And I have a problem with nested query in EF Core.

I have 2 classes:

public class PermissionGroupDefinitionEntity : IEntity
{
    public string Name { get; set; }
    public string NormalizedName { get; set; }
    public string DisplayName { get; set; }

    public virtual ICollection<PermissionDefinitionEntity> PermissionDefinitions { get; set; }
}

public class PermissionDefinitionEntity : IEntity
{
    public string Name { get; set; }
    public string NormalizedName { get; set; }
    public string DisplayName { get; set; }

    public bool IsEnabled { get; set; }
    public virtual string GroupName { get; set; }

    public virtual PermissionGroupDefinitionEntity Group { get; set; }
    public virtual ICollection<PermissionDefinitionEntity> Children { get; set; }
}

and this is the ApplicationDbContext:

        builder.Entity<PermissionDefinitionEntity>().HasOne(r => r.Group).WithMany(r => r.PermissionDefinitions).OnDelete(DeleteBehavior.Cascade);
        builder.Entity<PermissionDefinitionEntity>().HasOne(r => r.Parent).WithMany(r => r.Children).OnDelete(DeleteBehavior.Cascade);

I want query all PermissionGroupDefinitionEntity included PermissionDefinitionEntity and self referencing of PermissionDefinitionEntity.

Can I do that with EF Core?

5
  • 1
    You can't, at least not in one LINQ statement. This is a tree expansion of unknown depth, which requires recursive querying. Or if you want the whole tree, just query all PermissionGroupDefinitions and PermissionDefinitions (remove this redundant Entity suffix), which will populate all navigation properties. Commented Jul 11, 2021 at 9:06
  • So, I must be use recursive querying? Thanks for you support. Commented Jul 11, 2021 at 9:55
  • But can you explain about how can i get the whole tree? I don't understand why remove Entity suffix? I think it just class name. @gert-arnold Commented Jul 11, 2021 at 9:59
  • 1
    stackoverflow.com/a/41837737/861716. Removing the suffix is just an advice, it's useless and it reduces readability. Commented Jul 11, 2021 at 11:13
  • Thanks for your time. I think i'll use recursive querying for this problem. Commented Jul 11, 2021 at 13:47

2 Answers 2

3

You need to recursively load PermissionDefinitions that placed in the PermissionGroupDefinitionEntity.

First, you should load all PermissionGroupDefinitionEntities including its children using the following query :

var query = _dbContext.PermissionGroupDefinitionEntity
            .AsNoTracking()
            .Include(p => p.PermissionDefinitions )
            .ThenInclude(p => p.Children)
            .ToListAsync();

Since every PermissionGroupDefinitionEntity has a list of PermissionDefinition you need a nested loops like this code :

foreach (var PermissionGroupDefinitionEntity in PermissionGroupDefinitionEntities)
{
    foreach (var PermissionDefinitions in PermissionDefinitions)
    {

    }
}

Then in the inner loop you should call your recursive function.

See following link (sample for get all children recursively in Entity Framework Core)

https://patrickdesjardins.com/blog/how-to-load-hierarchical-structure-with-recursive-with-entity-framework-5

This way has terrible performance and I don't recommend that.

In this case it's seems you must write a stored procedure in SQL for better performance.

Sign up to request clarification or add additional context in comments.

Comments

0

You can use .ThenInclude(i => ...) like so

var query = _context.PermissionGroupDefinitionEntity
  .AsNoTracking()
  .Include(i => i.PermissionDefinitions)
      .ThenInclude(i => i.Group)
  .AsQueryable();

Edit:

var query = _context.PermissionGroupDefinitionEntity
  .AsNoTracking()
  .Include(i => i.PermissionDefinitions)
      .ThenInclude(i => i.Children)
  .AsQueryable();

3 Comments

Thanks for your support. But when i use this query. I received error: System.InvalidOperationException: 'The Include path 'PermissionDefinitions->Group' results in a cycle. Cycles are not allowed in no-tracking queries; either use a tracking query or remove the cycle.'. And when i remove AsNoTracking. This query return only first level of PermissionDefinitions.
Oh I think I misread the question, I've edited my answer so can you try and see if that fixes your issue.
Thank for your support. This query return maximum two-level of PermissionDefinition. As PermissionGroupDefinition => PermissionDefinition => PermissionDefinition. If i have struct PermissionGroupDefinition => PermissionDefinition => PermissionDefinition => PermissionDefinition it not working.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.