Closed hemirunner426 closed 3 weeks ago
@AndriySvyryd This seems to be caused by building the model externally from the context:
var modelBuilder = SqlServerConventionSetBuilder.CreateModelBuilder();
modelBuilder.Entity<TestModel>();
optionsBuilder.UseModel((IModel)modelBuilder.Model);
Explicitly finalizing the model doesn't help:
var modelBuilder = SqlServerConventionSetBuilder.CreateModelBuilder();
modelBuilder.Entity<TestModel>();
var finalizeModel = modelBuilder.FinalizeModel();
optionsBuilder.UseModel(finalizeModel);
@hemirunner426 As a workaround, configure the model in OnModelCreating
.
@ajcvickers Thanks for the suggestion I'll take a look to see if I can implement this workaround at design time in my production application.
This is a consequence of the model initialization breaking change
The full fix is:
public TestContext CreateDbContext(string[] args)
{
var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseSqlServer(@"Server=localhost;Database=TestDB;Trusted_Connection=True;");
var modelBuilder = SqlServerConventionSetBuilder.CreateModelBuilder();
modelBuilder.Entity<TestModel>();
var model = modelBuilder.Model.FinalizeModel();
var serviceContext = new TestContext(optionsBuilder.Options);
model = serviceContext.GetService<IModelRuntimeInitializer>().Initialize(model);
optionsBuilder.UseModel(model);
return new TestContext(optionsBuilder.Options);
}
We could add a check and throw an exception when this scenario is detected.
This is a consequence of the model initialization breaking change
The full fix is:
public TestContext CreateDbContext(string[] args) { var optionsBuilder = new DbContextOptionsBuilder(); optionsBuilder.UseSqlServer(@"Server=localhost;Database=TestDB;Trusted_Connection=True;"); var modelBuilder = SqlServerConventionSetBuilder.CreateModelBuilder(); modelBuilder.Entity<TestModel>(); var model = modelBuilder.Model.FinalizeModel(); var serviceContext = new TestContext(optionsBuilder.Options); model = serviceContext.GetService<IModelRuntimeInitializer>().Initialize(model); optionsBuilder.UseModel(model); return new TestContext(optionsBuilder.Options); }
We could add a check and throw an exception when this scenario is detected.
This workaround seemed to work. Thanks.
Fixing https://github.com/dotnet/efcore/issues/26186 would also fix this.
Note from triage: fixing this is complicated/risky. For now, we will document how to create an appropriate model to pass to UseModel.
@AndriySvyryd do we have a docs issue tracking documentation of this as a breaking change?
@ajcvickers It's already documented https://github.com/dotnet/EntityFramework.Docs/blob/main/entity-framework/core/what-is-new/ef-core-6.0/breaking-changes.md#snapshot-initialization Just hasn't been pushed to live
Hi! @AndriySvyryd . why do we have to create two instance from db context? another problem is we have a seperation with db context class and its dbcontextoptionsbuilder class and they are on different class libraries so we can not create object for dbcontext at method that uses model builder operations. or do you have a different suggestion for design time db context factoryr model producing?
@delikelli What is the reason for the dbcontextoptionsbuilder-related code to be in a different assembly? Perhaps there's a way of refactoring out the model building code so it can be also used for the design-time factory
Fixed in 9e7002c
Consider this model:
Along with a design time DbContext factory:
Running
dotnet ef migrations add Initial
produces the following migration:In previous versions of EF core the ID colum would be appended like the following:
When the EF 6 migration is applied to the database the ID column is not set as
Identity = True
. Thus, on insert the DbContext generates the following exception:EF Core version: 6.0.0 Database provider: Microsoft.EntityFrameworkCore.SqlServer Target framework: .NET 6.0 Operating system: Windows 11 IDE: Visual Studio 2022