dotnet / EntityFramework.Docs

Documentation for Entity Framework Core and Entity Framework 6
https://docs.microsoft.com/ef/
Creative Commons Attribution 4.0 International
1.59k stars 1.95k forks source link

Avoiding ServiceProvider rebuild with ConfigureWarnings #2210

Open CGollhardt opened 4 years ago

CGollhardt commented 4 years ago

The documentation is warning about the possibility that the service provider will be rebuild. But it doesn't show, how to avoid it.

When using OnConfiguring, is it rebuilded on every Context initialization? How can I configure it globaly?

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    //... Tenant specific configuration not shown

    // Globaly supress ByteIdentityColumnWarning
    // Performance Warning: https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbcontextoptionsbuilder.configurewarnings?view=efcore-3.1
    optionsBuilder.ConfigureWarnings(e => e.Ignore(SqlServerEventId.ByteIdentityColumnWarning));
}

Document Details

Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

ajcvickers commented 4 years ago

@CGollhardt Please attach a small, runnable project or post a small, runnable code listing that reproduces what you are seeing so that we can investigate.

CGollhardt commented 4 years ago

@ajcvickers I am refering to the documentation which states:

Note that changing this configuration can cause EF to build a new internal service provider, which may cause issues with performance. Generally it is expected that no more than one or two different configurations will be used for a given application.

Now I am not sure, how to configure it the way, so it will not cause to rebuild a new internal service provider every time I use the context.

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;

public class FooContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("connectionstring");
        optionsBuilder.ConfigureWarnings(e => e.Ignore(SqlServerEventId.ByteIdentityColumnWarning));
    }
}
ajcvickers commented 4 years ago

@CGollhardt If that's the configuration you are using and it's not changing from instance to instance, then you should at most get one of these warnings, which is then not a problem. If you're getting a warning for every context instance created, then something is going wrong, and hence the need for a repro.

CGollhardt commented 4 years ago

@ajcvickers thanks for your response.

It is working perfectly but I am worrying about the warning in the documentation, not which is logged by the DbContext. Hence I think we are talking about 2 different topics.

I get the DbContext warning only a single time:

The property 'DoorId' on entity type 'Doors' is of type 'byte', but is set up to use a SQL Server identity column. This requires that values starting at 255 and counting down will be used for temporary key values. A temporary key value is needed for every entity inserted in a single call to 'SaveChanges'. Care must be taken that these values do not collide with real key values.

However, I want to supress it. Hence I want to call:

optionsBuilder.ConfigureWarnings(e => e.Ignore(SqlServerEventId.ByteIdentityColumnWarning))

Now after reading the documentation of optionsBuilder.ConfigureWarnings, I am not left with a good feeling:

Note that changing this configuration can cause EF to build a new internal service provider, which may cause issues with performance. Generally it is expected that no more than one or two different configurations will be used for a given application.

For me, the documentation is missing the part what means can cause.

When I am creating a new Scope, e. g. (or by a new HttpRequest in MVC)

using (var scope = scopeFactory.CreateScope())
{
    var dbContext = scope.ServiceProvder.GetRequiredService<FooDbContext>();
    dbContext.Foo.ToList();
}

The OnConfiguring method of the context is excecuted:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseSqlServer("connectionstring");
    optionsBuilder.ConfigureWarnings(e => e.Ignore(SqlServerEventId.ByteIdentityColumnWarning));
}

And with this optionsBuilder.ConfigureWarnings is executed. Does this mean, the Service Provider is destroyed every time? What are the alternatives?

My intention is to generaly ignore the warning SqlServerEventId.ByteIdentityColumnWarning. It should be always the same and should not change anywhere in my application.

ajcvickers commented 4 years ago

@CGollhardt Normally EF Core only creates one internal service provider to use for all DbContext instances that your application creates. However, some options require a different internal service provider to be created if those options are changed. In your case, since you're not changing the options between different context instances this code won't kick in, and you'll still only have one internal service provider for your app, which is good.

In other words, don't worry about it--you're not doing what it is warning against. :smile:

I'll try to update the docs to be a bit clearer on this.

Simonl9l commented 3 years ago

For clarity, is there a specific logging action that could be added (if not already there) that warns if subsequent service providers are created (i.e if the service provider is re-created)?

ajcvickers commented 3 years ago

@Simonl9l EF Core will log when it rebuilds the service provider. See https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.diagnostics.coreeventid.serviceprovidercreated?view=efcore-5.0

Simonl9l commented 3 years ago

You get that on any creation? Not just recreation after the initial creation? One could set up a .Throw if was any re-creation with ConfigureWarnings