Efcore: Migration ef core 2.2 to 3.1 with owned entities

Created on 4 Feb 2020  路  8Comments  路  Source: dotnet/efcore

Observed Behavior

I'm struggling with one of the breaking changes from ef core 2.2 to ef core 3.1. The breaking change that I'm talking about is the 'Owned' breaking change. I've tried many settings to resolve the problem that I'm facing, but until now, nothing has worked. My question is what must I do so that I can migrate from ef core 2.2 to ef core 3.1 succesfully (so that I'm able to use my context in the application without any data loss)?

I've managed to create a small test project where my problem is located which can be found here:
repository

I've tried and read the solutions from other people, but still no success:

https://github.com/dotnet/efcore/issues/18092 https://github.com/dotnet/efcore/issues/15681 https://github.com/dotnet/efcore/issues/9873

https://stackoverflow.com/questions/57692369/ef-core-configuration-problem-with-owned-type-used-in-2-different-classes
https://docs.microsoft.com/en-us/ef/core/modeling/owned-entities

The error that I'm experiencing is as follow:

PM> Add-Migration Test
Build started...
Build succeeded.
System.InvalidOperationException: The type 'ContactInfo' cannot be configured as non-owned because an owned entity type with the same name already exists.
   at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalModelBuilder.Entity(TypeIdentity& type, ConfigurationSource configurationSource, Nullable`1 shouldBeOwned)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalModelBuilder.Entity(Type type, ConfigurationSource configurationSource, Nullable`1 shouldBeOwned)
   at Microsoft.EntityFrameworkCore.ModelBuilder.Entity[TEntity]()
   at TestProject.Context.TestDbContext.OnModelCreating(ModelBuilder modelBuilder) in C:\Users\mmpeeters\source\repos\TestProject\TestProject\Context\TestDbContext.cs:line 18
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelCustomizer.Customize(ModelBuilder modelBuilder, DbContext context)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, IConventionSetBuilder conventionSetBuilder)
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
   at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__7_3(IServiceProvider p)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
   at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
   at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure<System.IServiceProvider>.get_Instance()
   at Microsoft.EntityFrameworkCore.Infrastructure.Internal.InfrastructureExtensions.GetService[TService](IInfrastructure`1 accessor)
   at Microsoft.EntityFrameworkCore.Infrastructure.AccessorExtensions.GetService[TService](IInfrastructure`1 accessor)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func`1 factory)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
The type 'ContactInfo' cannot be configured as non-owned because an owned entity type with the same name already exists.

The main question is, what can I do to resolve this error? :-)

Expected Behavior

That I'm able to run migrations and even better that I'm able to use the DbContext in the web project without this error.

Steps to reproduce

Github project: repository

Further technical details

EF Core version: 3.1.1
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET Core 3.1
Operating system: Windows 10
IDE: Visual Studio 2019 Preview 16.5.0 (Preview 2)

closed-question customer-reported

All 8 comments

@michielpeeters The top-level Entity method cannot be used to configure an owned type. So, instead of this:

```C#
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity().OwnsOne(c => c.Info);
modelBuilder.Entity().OwnsOne(c => c.Info);
modelBuilder.Entity().OwnsOne(c => c.Info);

modelBuilder.Entity<ContactInfo>()
    .Property<byte[]>("RowVersion").IsRowVersion().HasColumnName("RowVersion");

base.OnModelCreating(modelBuilder);

}


Do this:

```C#
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<BigCustomer>()
        .OwnsOne(
            c => c.Info, 
            b=> b.Property<byte[]>("RowVersion").IsRowVersion().HasColumnName("RowVersion"));


    modelBuilder
        .Entity<SmallCustomer>()
        .OwnsOne(
            c => c.Info, 
            b=> b.Property<byte[]>("RowVersion").IsRowVersion().HasColumnName("RowVersion"));

    modelBuilder
        .Entity<ProjectCustomer>()
        .OwnsOne(
            c => c.Info, 
            b=> b.Property<byte[]>("RowVersion").IsRowVersion().HasColumnName("RowVersion"));
    base.OnModelCreating(modelBuilder);
}

However, that's not working for me either. @AndriySvyryd Any ideas?

Code:

```C#
[Table("Customers")]
public abstract class CustomerBase
{
[Key]
public int Id { get; set; }

[Required]
public string Name { get; set; }

[Timestamp]
public byte[] RowVersion { get; set; }

}

public class BigCustomer : CustomerBase
{
public ContactInfo Info { get; set; }
}

[Owned]
public class ContactInfo
{
[Required]
public string FirstName { get; set; }

[Required]
public string LastName { get; set; }

[Required]
public string Email { get; set; }

}

public class ProjectCustomer : CustomerBase
{
public ContactInfo Info { get; set; }
}

public class SmallCustomer : CustomerBase
{
public ContactInfo Info { get; set; }
}

public class BloggingContext : DbContext
{
private readonly ILoggerFactory Logger
= LoggerFactory.Create(c => c.AddConsole());//.SetMinimumLevel(LogLevel.Debug));

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .UseLoggerFactory(Logger)
        .EnableSensitiveDataLogging()
        .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Test;ConnectRetryCount=0");
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<CustomerBase>();

    modelBuilder
        .Entity<BigCustomer>()
        .OwnsOne(
            c => c.Info, 
            b=> b.Property<byte[]>("RowVersion").IsRowVersion().HasColumnName("RowVersion"));

    modelBuilder
        .Entity<SmallCustomer>()
        .OwnsOne(
            c => c.Info, 
            b=> b.Property<byte[]>("RowVersion").IsRowVersion().HasColumnName("RowVersion"));

    modelBuilder
        .Entity<ProjectCustomer>()
        .OwnsOne(
            c => c.Info, 
            b=> b.Property<byte[]>("RowVersion").IsRowVersion().HasColumnName("RowVersion"));

    base.OnModelCreating(modelBuilder);
}

}

public class Program
{
public static async Task Main()
{
using (var context = new BloggingContext())
{
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
}
}
}


Exception:

s\dotnet\dotnet.exe" C:/Stuff/Local/ThreeOne/bin/Debug/netcoreapp3.1/ThreeOne.dll
application data, this mode should only be enabled during development.
Unhandled exception. System.InvalidOperationException: Entity type 'BigCustomer' doesn't contain a property mapped to the store-generated concurrency token column 'RowVersion' that is used by
another entity type sharing the table 'Customers'. Add a store-generated property mapped to the same column to 'BigCustomer'. It can be in shadow state.
at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.ValidateSharedColumnsCompatibility(IReadOnlyList1 mappedTypes, String tableName, IDiagnosticsLogger1 logger)
at Microsoft.EntityFrameworkCore.SqlServer.Internal.SqlServerModelValidator.ValidateSharedColumnsCompatibility(IReadOnlyList1 mappedTypes, String tableName, IDiagnosticsLogger1 logger)
at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.ValidateSharedTableCompatibility(IModel model, IDiagnosticsLogger1 logger) at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.Validate(IModel model, IDiagnosticsLogger1 logger)
at Microsoft.EntityFrameworkCore.SqlServer.Internal.SqlServerModelValidator.Validate(IModel model, IDiagnosticsLogger1 logger) at Microsoft.EntityFrameworkCore.Metadata.Conventions.ValidatingConvention.ProcessModelFinalized(IConventionModelBuilder modelBuilder, IConventionContext1 context)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnModelFinalized(IConventionModelBuilder modelBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.OnModelFinalied(IConventionModelBuilder modelBuilder)
at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.FinalizeModel()
at Microsoft.EntityFrameworkCore.ModelBuilder.FinalizeModel()
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, IConventionSetBuilder conventionSetBuilder)
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.b__7_3(IServiceProvider p)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProv iderEngine, RuntimeResolverLock lockType) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProv iderEngine, RuntimeResolverLock lockType) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.b__0(ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngine.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredServiceT
at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Infrastructure.IInfrastructure.get_Instance()
at Microsoft.EntityFrameworkCore.Infrastructure.Internal.InfrastructureExtensions.GetServiceTService
at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.get_Dependencies()
at Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade.EnsureDeleted()
at Program.Main() in C:\Stuff\LocalThreeOne\Program.cs:line 114
at Program.

()
```

You also need to map the RowVersion on CustomerBase to the same column:
C# modelBuilder.Entity<CustomerBase>() .Property(c => c.RowVersion).HasColumnName("RowVersion");

@ajcvickers Do you think that the exception message should be improved?

@AndriySvyryd Maybe. I should have tried explicitly mapping it, but I was expecting to already map to that column. Why does it need explicit configuration here? Is it because RowVersion is explicitly mapped by other types, so we then uniquify the by-convention mapping for the column name?

Why does it need explicit configuration here? Is it because RowVersion is explicitly mapped by other types, so we then uniquify the by-convention mapping for the column name?

Yes. We uniquify all names not specified explicitly if there's a collision.

Thank you for the responses. I was able to resolve my problem! Maybe it is an idea to mention that uniquify in the documentation?

hello is this issue being resolved?

i tried handled the owned entities and i am returning with the same error.

System.InvalidOperationException: The type 'SamuraiApp.Domain.PersonFullName' cannot be configured as non-owned because an owned entity type with the same name already exists.
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalModelBuilder.Entity(TypeIdentity& type, ConfigurationSource configurationSource, Nullable1 shouldBeOwned) at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalModelBuilder.Entity(String name, ConfigurationSource configurationSource, Nullable1 shouldBeOwned)
at Microsoft.EntityFrameworkCore.ModelBuilder.Entity(String name)
at SamuraiAppEF.Data.SamuraiContext.OnModelCreating(ModelBuilder modelBuilder) in C:\Users\clouddust-dell\source\repos\SamuraiApp\SamuraiApp\SamuraiAppEF.Data\SamuraiContext.cs:line 74
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder)
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, IConventionSetBuilder conventionSetBuilder)
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite singletonCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(ServiceCallSite callSite, TArgument argument)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredServiceT
at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
at Microsoft.EntityFrameworkCore.Infrastructure.Internal.InfrastructureExtensions.GetServiceTService
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
The type 'SamuraiApp.Domain.PersonFullName' cannot be configured as non-owned because an owned entity type with the same name already exists.

Code:
`

public class Battle
{
    public Battle() {
        SamuraiBattles = new List<SamuraiBattle>();
    }
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
    //public List<Samurai> Samurais { get; set; }
    public List<SamuraiBattle> SamuraiBattles { get; set; }
}

public class SecretIdentity
{
    public int Id { get; set; }
    public string RealName { get; set; }
    //public int? SamuraiFK { get; set; } //Question mark allows nullubale dependents
    //
    public int SamuraiId { get; set; }

    //public Samurai Samurai { get; set; }//if you want to navigate secret identity to samurai
}

public class Quote
{
    public int Id { get; set; }
    public string Text { get; set; }
    public Samurai Samurai { get; set; }
    public int SamuraiId { get; set; }
}

public class SamuraiBattle
{
    public int SamuraiId { get; set; }
    public Samurai Samurai { get; set; }
    public int BattleId { get; set; }
    public Battle Battle { get; set; }
}
[Owned]
public class PersonFullName
{
    public PersonFullName(string givenName, string surName) {
        SurName     = surName;
        GivenName   = givenName;
    }
    public string SurName { get; set; }
    public string GivenName { get; set; }
}

public class Samurai : ITimeStamp
{
    public Samurai() {
        Quotes = new List<Quote>();
        SamuraiBattles = new List<SamuraiBattle>();
    }
    //if e require gyd and one to one use business logic
    public Samurai(string publicName, string secretName) : this() {
        Name = publicName;
        SecretIdentity = new SecretIdentity { RealName = secretName };
    }
    //
    public int Id { get; set; }
    public string Name { get; set; }
    public string LastName { get; set; }
    public PersonFullName BetterName { get; set; }
    //
    public List<Quote> Quotes { get; set; }
    public List<SamuraiBattle> SamuraiBattles { get; set; }
    public SecretIdentity SecretIdentity { get; set; }
    //
    public DateTime DateCreated { get; set; }
    public DateTime DateUpdated { get; set; }
    //
    public string CompleteName => LastName + ", " + Name;
    //
}

`

Context Class:

`
public SamuraiContext()
{

    }

    public DbSet<Samurai> Samurais { get; set; }
    public DbSet<Quote> Quotes { get; set; }
    public DbSet<Battle> Battles { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
        optionsBuilder
            .UseMySql(_connectionString);
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder) {
        modelBuilder.Entity<SamuraiBattle>(entity => {
            entity.HasKey(s => new { s.SamuraiId, s.BattleId });
        });
        modelBuilder.Entity<Battle>().Property(c => c.StartDate).HasColumnType("Date");
        modelBuilder.Entity<Battle>().Property(c => c.EndDate).HasColumnType("Date");
        //
        modelBuilder.Entity<Samurai>(entity => {
            entity.UseTimestampedProperty();
            entity.HasKey(e => e.Id);
            entity.OwnsOne(m => m.BetterName);
        });
        foreach (var entityType in modelBuilder.Model.GetEntityTypes()) {
            modelBuilder.Entity(entityType.Name).Property<DateTime>("Created");
            modelBuilder.Entity(entityType.Name).Property<DateTime>("LastModified");
        }

    }

`

Some handling for shadow properties are also being implemented.

@clouddust0246 Don't call modelBuilder.Entity(entityType.Name), instead configure the properties in the OwnsOne call. See docs

I had the same issue, and the fix was as following.
After changing the configuration to 3.0 the end result should be any empty migration, which means the model hasn't been changed.

the model I was working on is the following:

public class SchedulerSession:AggregateRoot
    {
        public List<SchedulerSessionStep> Steps { get; set; }
        public double ElapsedSeconds { get; set; }
        public List<SchedulerSessionCounter> Counters { get; set; }
    }

public class SchedulerSessionStep 
    {
        public string Name { get; set; }
        public double ElapsedSeconds { get; set; }
        public List<SchedulerSessionStepError> Errors { get; set; }
    }
 public class SchedulerSessionStepError
    {
        public string Error { get; set; }
        public string Description { get; set; }
        public string Exception { get; set; }
        public string StackTrace { get; set; }
    }
public class SchedulerSessionCounter
    {
        public string Name { get; set; }
        public int Value { get; set; }
    }

The configuration I used was:

modelBuilder.Entity<SchedulerSession>().OwnsOne(s => s.Changes);
modelBuilder.Entity<SchedulerSession>().OwnsMany(s => s.Steps);
modelBuilder.Entity<SchedulerSessionStep>().OwnsMany(ss => ss.Errors);
modelBuilder.Entity<SchedulerSession>().OwnsMany(s => s.Counters);

modelBuilder.Entity<SchedulerSessionStep>().Property<int>("Id");
modelBuilder.Entity<SchedulerSessionStep>().HasKey("Id");
modelBuilder.Entity<SchedulerSessionStepError>().Property<int>("Id");
modelBuilder.Entity<SchedulerSessionStepError>().HasKey("Id");
modelBuilder.Entity<SchedulerSessionCounter>().Property<int>("Id");
modelBuilder.Entity<SchedulerSessionCounter>().HasKey("Id");

The new configuration:

modelBuilder.Entity<SchedulerSession>().OwnsOne(session => session.Changes);
modelBuilder.Entity<SchedulerSession>().OwnsMany(session => session.Steps, step =>
            {
                step.Property<int>("Id");
                step.HasKey("Id");
                step.OwnsMany(s => s.Errors, error =>
                {
                    error.Property<int>("Id");
                    error.HasKey("Id");
                }).WithOwner();
            });
modelBuilder.Entity<SchedulerSession>().OwnsMany(session => session.Counters, counter =>
            {
                counter.Property<int>("Id");
                counter.HasKey("Id");
            });

Add a migration and call it Sync to test.
The result was a migration with all tables created again.

After some investigation, I found there were some changes to the file: ApplicationDbContextModelSnapshot

The changes apparently not changing the model, but changing Model builder version to 3.1.4:

modelBuilder
                .HasAnnotation("ProductVersion", "3.1.4")
                .HasAnnotation("Relational:MaxIdentifierLength", 128)
                .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);

And some changes related to defining columns properties, for example:

b.Property<Guid>("AggregateId");

Becomes

 b.Property<Guid>("AggregateId")
                        .HasColumnType("uniqueidentifier");

I deleted the sync migration.

Added it again and it was empty.

Delete the second migration since it's empty.

Run the application and it was intact.

Hope this will help someone.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

HappyNomad picture HappyNomad  路  3Comments

ryanwinter picture ryanwinter  路  3Comments

bgribaudo picture bgribaudo  路  3Comments

leak picture leak  路  3Comments

miguelhrocha picture miguelhrocha  路  3Comments