Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiled model: Allow use of lazy loading and change tracking proxy types. #24902

Closed
Tracked by #22952
AndriySvyryd opened this issue May 13, 2021 · 14 comments · Fixed by #28127
Closed
Tracked by #22952

Compiled model: Allow use of lazy loading and change tracking proxy types. #24902

AndriySvyryd opened this issue May 13, 2021 · 14 comments · Fixed by #28127
Assignees
Labels
area-model-building area-proxies closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-enhancement
Milestone

Comments

@AndriySvyryd
Copy link
Member

Depends on #24898

@viniciusverasdossantos
Copy link

Hi. Will we be able to CompiledModel with UseLazyLoadingProxies until the final version of .NET 6?

@AndriySvyryd
Copy link
Member Author

@viniciusverasdossantos No, this issue is in the Backlog, so we don't have plans for shipping it in any specific release yet

@viniciusverasdossantos
Copy link

@viniciusverasdossantos Não, este problema está no Backlog, então não temos planos para enviá-lo em nenhum lançamento específico ainda

I am suffering a lot with my 550 entity model in development due to the delay each time I compile. I use lazyload and changetrackproxy. For Lazy Load if I implement the manual form in each class I will be able to use the CompiledModel right? Is there a similar alternative for ChangeTrackProxy? Well, I use both resources.

@AndriySvyryd
Copy link
Member Author

@viniciusverasdossantos You might be hitting #20135, where proxy type creating is taking longer for each type.

For change tracking you can implement INotifyPropertyChanging and INotifyPropertyChanged.

@viniciusverasdossantos
Copy link

viniciusverasdossantos commented May 2, 2022

Hi. Will we be able to CompiledModel with UseLazyLoadingProxies until the final version of .NET 7?

@ajcvickers
Copy link
Member

@viniciusverasdossantos This issue is in the Backlog milestone. This means that it is not planned for the next release (EF Core 7.0). We will re-assess the backlog following the this release and consider this item at that time. However, keep in mind that there are many other high priority features with which it will be competing for resources. Make sure to vote (👍) for this issue if it is important to you.

@viniciusverasdossantos
Copy link

@viniciusverasdossantos This issue is in the Backlog milestone. This means that it is not planned for the next release (EF Core 7.0). We will re-assess the backlog following the this release and consider this item at that time. However, keep in mind that there are many other high priority features with which it will be competing for resources. Make sure to vote (👍) for this issue if it is important to you.

This is very slow development on my model with more than 600 entities. I really hope this feature because it's a huge job to refactor all entities to get the compiled model. Thanks

@ajcvickers ajcvickers changed the title Compiled model: Generate custom lazy loading and change tracking proxy types. Compiled model: Generate allow use of lazy loading and change tracking proxy types. May 30, 2022
@ajcvickers ajcvickers self-assigned this May 30, 2022
@ajcvickers ajcvickers modified the milestones: Backlog, 7.0.0 May 30, 2022
@ajcvickers ajcvickers added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label May 30, 2022
ajcvickers added a commit that referenced this issue May 30, 2022
Part of #626
Part of #15911
Fixes #20135
Fixes #14554
Fixes #24902

This is the lowest level of materialization interception--it allows the actual constructor/factory binding to be changed, such that the expression tree for the compiled delegate is altered.

Introduces singleton interceptors, which cannot be changed per context instance without re-building the internal service provider. (Note that we throw by default if this is abused and results in many service providers being created.)

The use of this for proxies has two big advantages:
- Proxy types are created lazily, which vastly improves model building time for big models with proxies. See #20135.
- Proxies can now be used with the compiled model, since the proxy types are not compiled into the model. See
@ajcvickers ajcvickers changed the title Compiled model: Generate allow use of lazy loading and change tracking proxy types. Compiled model: Allow use of lazy loading and change tracking proxy types. May 30, 2022
ajcvickers added a commit that referenced this issue Jun 1, 2022
Part of #626
Part of #15911
Fixes #20135
Fixes #14554
Fixes #24902

This is the lowest level of materialization interception--it allows the actual constructor/factory binding to be changed, such that the expression tree for the compiled delegate is altered.

Introduces singleton interceptors, which cannot be changed per context instance without re-building the internal service provider. (Note that we throw by default if this is abused and results in many service providers being created.)

The use of this for proxies has two big advantages:
- Proxy types are created lazily, which vastly improves model building time for big models with proxies. See #20135.
- Proxies can now be used with the compiled model, since the proxy types are not compiled into the model. See
@viniciusverasdossantos
Copy link

thank you very much

@ajcvickers ajcvickers removed this from the 7.0.0 milestone Jun 20, 2022
@dneeper
Copy link

dneeper commented Dec 30, 2022

I'm using the latest 7.0.1 version of the Microsoft.EntityFrameworkCore.Design, .Proxies and .Relational packages, and have installed the latest 7.0.1 version of the dotnet-ef tool. I've spent the past few days trying to get Lazy Loading proxies to work with the compiled model, without having any luck. Adding .UseModel() to the options builder always results in the poco entity class being returned from EF queries, instead of the Castle proxy. The What's New In EF Core 7.0 page claims that Lazy Loading proxies now work with Compiled Models, and I was hoping you could share any insights for setting it up?

public class CATSContextFactory : IContextFactory<CATSContext>
{
	public CATSContext Create(string dbConnection, ILoggerFactory loggerFactory = null)
	{
		var serverVersion = ServerVersion.AutoDetect(dbConnection);

		var optionsBuilder = new DbContextOptionsBuilder<CATSContext>()
			.UseMySql(dbConnection, serverVersion)
			.UseLazyLoadingProxies()
			.UseModel(CATSContextModel.Instance)
			.EnableThreadSafetyChecks();

		if (loggerFactory != null)
		{
			optionsBuilder.UseLoggerFactory(loggerFactory);
		}

		return new CATSContext(optionsBuilder.Options);
	}
}

@ajcvickers
Copy link
Member

@dneeper It's working for me--see my test code below. If you're still running into an issue, then please open a new issue and attach a small, runnable project or post a small, runnable code listing that reproduces what you are seeing so that we can investigate.

public class Blog
{
    public int Id { get; set; }
    public virtual List<Post> Posts { get; } = new();
}

public class Post
{
    public int Id { get; set; }
    public int? BlogId { get; set; }
    public virtual Blog? Blog { get; set; }
}

public class SomeDbContext : DbContext
{
    public DbSet<Blog> Blogs => Set<Blog>();
    public DbSet<Post> Posts => Set<Post>();

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        => optionsBuilder
            .UseModel(SomeDbContextModel.Instance)
            .UseLazyLoadingProxies()
            .UseSqlServer(@"Data Source=(LocalDb)\MSSQLLocalDB;Database=AllTogetherNow")
            .LogTo(Console.WriteLine, LogLevel.Information)
            .EnableSensitiveDataLogging();
}

public class Program
{
    public static async Task Main()
    {
        using (var context = new SomeDbContext())
        {
            // await context.Database.EnsureDeletedAsync();
            // await context.Database.EnsureCreatedAsync();

            context.Add(new Post { Blog = new() });

            await context.SaveChangesAsync();
        }

        using (var context = new SomeDbContext())
        {
            var post = context.Posts.First();
            Console.WriteLine(post.GetType());
            Console.WriteLine(post.Blog!.Id);
        }
    }
}

@sccrgoalie1
Copy link

@dneeper It didn't work for us at first either. Then realized in production we called UseLazyLoadingProxies, but in our IDesignTimeDbContextFactory we were not. Once we added that and regenerated the models, all was good.

@dneeper
Copy link

dneeper commented Jan 20, 2023

I did find my problem - I was setting the options and creating the context in the ContextFactory, but, I needed to call UseLazyLoadingProxies() in the OnConfiguring() method so that the external process that compiled the model would know to use proxies. It works great now!

@tacktaro
Copy link

I did find my problem - I was setting the options and creating the context in the ContextFactory, but, I needed to call UseLazyLoadingProxies() in the OnConfiguring() method so that the external process that compiled the model would know to use proxies. It works great now!

Hi @dneeper , can you help me with the code?

@MaxwellDAssistek
Copy link

If this issue is resolved, documentation should be updated here: https://learn.microsoft.com/en-us/ef/core/performance/advanced-performance-topics?tabs=with-di%2Csimple-with-parameter#limitations-1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-model-building area-proxies closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. type-enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants