skip to Main Content

EF Core 6 introduced the ability to auto-include navigations (https://learn.microsoft.com/en-us/ef/core/querying/related-data/eager#model-configuration-for-auto-including-navigations).I have a model that is related to multiple tables and I would like to configure it to auto-include multiple related tables but have been unable to figure out how to do it. Is this supported?

This is the current setup.

            modelBuilder.Entity<ExampleModel>()
            .UseXminAsConcurrencyToken()
            .Navigation(e => e.ExampleModelRelatedItem1).AutoInclude()
            .AutoInclude();

I have tried variations such as

            modelBuilder.Entity<ExampleModel>()
            .UseXminAsConcurrencyToken()
            .Navigation(e => e.ExampleModelRelatedItem1).AutoInclude()
            .Navigation(e => e.ExampleModelRelatedItem2).AutoInclude()
            .AutoInclude();

but can’t find anything that works.

2

Answers


  1. Of course the .AutoInclude() implementation has a more complex logic but under the hood it uses the .SetIsEagerLoaded(bool?) method.

    Here is an extension method that could be a good starting point.
    It’s kind of ‘brute force’ as it tries to find a navigation for each and every property of the entity.

    public static void AutoInclude(this IMutableEntityType entityType)
    {
        var entityClrTypes =
            entityType
                .Model
                .GetEntityTypes()
                .Select(entityType => entityType.ClrType)
                .ToList();
    
        entityType
            .GetProperties()
            .Where(
                entityType =>
                entityClrTypes.Contains(entityType.ClrType)
            )
            .Select(
                entityProperty =>
                entityType.FindNavigation(entityProperty.Name) // can be null
            )
            .OfType<IMutableNavigation>() // filter null
            .ToList()
            .ForEach(navigation => navigation.SetIsEagerLoaded(true));
    }
    
    // Usage
    modelBuilder.Entity<Person>(
        entityTypeBuilder =>
        entityTypeBuilder.Metadata.AutoInclude()
    );
    
    // Usage for your example
    modelBuilder
        .Entity<ExampleModel>(
            entityTypeBuilder =>
            entityTypeBuilder.Metadata.AutoInclude()
        )
        .UseXminAsConcurrencyToken()
    

    Hope that helps.

    Login or Signup to reply.
  2. Looks like you are thinking that the whole configuration should be with single fluent API call chain.

    Which is true for fluent APIs that return the EntityTypeBuilder<T> (from ModelBuilder.Entity<T>() call) they are called on.

    However many configuration APIs (like Property, Navigation, HasMany, HasOne, OwnsOne, OwnsMany etc.) return different builder providing specific fluent APIs for it.

    So what you need is to simply "restart" the fluent chain. This could be done in several way. For instance, with another Entity<T>() call

    modelBuilder.Entity<ExampleModel>()
        .UseXminAsConcurrencyToken();
    
    modelBuilder.Entity<ExampleModel>()
        .Navigation(e => e.ExampleModelRelatedItem1).AutoInclude();
    
    modelBuilder.Entity<ExampleModel>()
        .Navigation(e => e.ExampleModelRelatedItem2).AutoInclude();
    

    or with Entity<T>() overload with builder action

    modelBuilder.Entity<ExampleModel>(builder =>
    {
        builder.UseXminAsConcurrencyToken();
    
        builder.Navigation(e => e.ExampleModelRelatedItem1).AutoInclude();
    
        builder.Navigation(e => e.ExampleModelRelatedItem2).AutoInclude();
    });
    

    or using local variable

    {
        var builder = modelBuilder.Entity<ExampleModel>();
    
        builder.UseXminAsConcurrencyToken();
    
        builder.Navigation(e => e.ExampleModelRelatedItem1).AutoInclude();
    
        builder.Navigation(e => e.ExampleModelRelatedItem2).AutoInclude();
    }
    

    or private or local method receiving EntityTypeBuilder<T>, or class implementing IEntityTypeConfiguration<T> with Apply method receiving the same, etc.

    The essential is to configure each navigation (AutoInclude or whatever) separately by starting with Navigation method from EnityTypeBuilder<T> obtained somehow.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search