Upgraded to ef core 3.0 and OwnsMany calls are giving the following error:


The entity:

The valueobject:

This was working in the previous ef core version
Intentional breaking change as per #9148
@AndriySvyryd - Do you want to add this to breaking changes doc?
@codehunter13 - I could not see where you are configuring UserNotification as regular entity in your code snippets but running the code snippets you posted also does not throw exception for me.
Can you verify that you are hitting what is in #9148? If not can you provide a full repro code which shows the issue?
I have the same error after upgrade
_InvalidOperationException: The type 'OwnedCustomerName' cannot be marked as owned because a non-owned entity type with the same name already exists._
That's my code
public class CustomerContact
{
public CustomerContact()
{
}
public string EmailAddress { get; set; }
public string Phone { get; set; }
}
public class CustomerName
{
public CustomerName()
{
this.Contact = new CustomerContact();
}
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public CustomerContact Contact { get; set; }
}
modelBuilder.Entity<CustomerName>(entity =>
{
entity.OwnsOne(x => x.Contact).Property(c => c.EmailAddress).HasColumnName("EmailAddress").HasMaxLength(50);
entity.OwnsOne(x => x.Contact).Property(c => c.Phone).HasColumnName("Phone").HasColumnType("Phone")
.HasMaxLength(25);
});
modelBuilder.Entity<Customer>(entity =>
{
entity.ToTable("Customer", "SalesLT");
entity.Ignore(e => e.AddressCount);
entity.HasIndex(e => e.Rowguid)
.HasName("AK_Customer_rowguid")
.IsUnique();
entity.Property(e => e.CustomerId).HasColumnName("CustomerID");
entity.Property(e => e.CompanyName).HasMaxLength(128);
#region Owned Types
entity.OwnsOne(x => x.CustomerName).Property(c => c.FirstName).HasColumnName("FirstName").IsRequired()
.HasColumnType("Name")
.HasMaxLength(50);
entity.OwnsOne(x => x.CustomerName).Property(c => c.MiddleName).HasColumnName("MiddleName")
.HasColumnType("Name")
.HasMaxLength(50);
entity.OwnsOne(x => x.CustomerName).Property(c => c.LastName).HasColumnName("LastName").IsRequired()
.HasColumnType("Name")
.HasMaxLength(50);
#endregion
entity.Property(e => e.ModifiedDate)
.HasColumnType("datetime")
.HasDefaultValueSql("(getdate())");
entity.Property(e => e.NameStyle).HasColumnType("NameStyle");
entity.Property(e => e.PasswordHash)
.IsRequired()
.HasMaxLength(128)
.IsUnicode(false);
entity.Property(e => e.PasswordSalt)
.IsRequired()
.HasMaxLength(10)
.IsUnicode(false);
entity.Property(e => e.Rowguid)
.HasColumnName("rowguid")
.HasDefaultValueSql("(newid())");
entity.Property(e => e.SalesPerson).HasMaxLength(256);
entity.Property(e => e.Suffix).HasMaxLength(10);
entity.Property(e => e.Title).HasMaxLength(8);
});
I got the error in two situations:

@codehunter13 The exception was introduced to catch configuration like that. It might have worked for your model, but in general it's not supported and could've let to unexpected behavior.
Looks like i solved this too by changing configuration. Thanks.
modelBuilder.Entity<Customer>(entity =>
{
entity.ToTable("Customer", "SalesLT");
entity.Ignore(e => e.AddressCount);
entity.HasIndex(e => e.Rowguid)
.HasName("AK_Customer_rowguid")
.IsUnique();
entity.Property(e => e.CustomerId).HasColumnName("CustomerID");
entity.Property(e => e.CompanyName).HasMaxLength(128);
#region Owned Types
var ownedCustName = entity.OwnsOne(x => x.CustomerName);
ownedCustName.Property(c => c.FirstName).HasColumnName("FirstName").IsRequired()
.HasColumnType("Name")
.HasMaxLength(50);
ownedCustName.Property(c => c.MiddleName).HasColumnName("MiddleName")
.HasColumnType("Name")
.HasMaxLength(50);
ownedCustName.Property(c => c.LastName).HasColumnName("LastName").IsRequired()
.HasColumnType("Name")
.HasMaxLength(50);
var ownedContact = ownedCustName.OwnsOne(x => x.Contact);
ownedContact.Property(c => c.EmailAddress).HasColumnName("EmailAddress").HasMaxLength(50);
ownedContact.Property(c => c.Phone).HasColumnName("Phone").HasColumnType("Phone")
.HasMaxLength(25);
#endregion
entity.Property(e => e.ModifiedDate)
.HasColumnType("datetime")
.HasDefaultValueSql("(getdate())");
entity.Property(e => e.NameStyle).HasColumnType("NameStyle");
entity.Property(e => e.PasswordHash)
.IsRequired()
.HasMaxLength(128)
.IsUnicode(false);
entity.Property(e => e.PasswordSalt)
.IsRequired()
.HasMaxLength(10)
.IsUnicode(false);
entity.Property(e => e.Rowguid)
.HasColumnName("rowguid")
.HasDefaultValueSql("(newid())");
entity.Property(e => e.SalesPerson).HasMaxLength(256);
entity.Property(e => e.Suffix).HasMaxLength(10);
entity.Property(e => e.Title).HasMaxLength(8);
});
@AndriySvyryd Yep, this is a breaking change. And I can change code, but it's not cool that I have to change ContextModelSnapshot, i.e. I have no chance for rollback now as I understood.
System.InvalidOperationException: The type 'Connect.Device.BusinessModel.Values.OrganizationAddress' 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(String name, ConfigurationSource configurationSource, Nullable`1 shouldBeOwned)
at Microsoft.EntityFrameworkCore.Metadata.Builders.OwnedNavigationBuilder.FindRelatedEntityType(String relatedTypeName, String navigationName)
at Microsoft.EntityFrameworkCore.Metadata.Builders.OwnedNavigationBuilder.HasOne(String relatedTypeName, String navigationName)
at Microsoft.EntityFrameworkCore.Metadata.Builders.OwnedNavigationBuilder.HasOne(String navigationName)
at Connect.Device.DAL.Migrations.Migrations.DeviceContextModelSnapshot.<>c.<BuildModel>b__0_42(OwnedNavigationBuilder b2) in C:\Users\pavelvoronin\Source\Repos\connect.device\Connect.Device.DAL.Migrations\Migrations\DeviceContextModelSnapshot.cs:line 3093
at Microsoft.EntityFrameworkCore.Metadata.Builders.OwnedNavigationBuilder.OwnsOne(String ownedTypeName, String navigationName, Action`1 buildAction)
at Connect.Device.DAL.Migrations.Migrations.DeviceContextModelSnapshot.<>c.<BuildModel>b__0_39(OwnedNavigationBuilder b1) in C:\Users\pavelvoronin\Source\Repos\connect.device\Connect.Device.DAL.Migrations\Migrations\DeviceContextModelSnapshot.cs:line 3077
at Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder.OwnsOne(String ownedTypeName, String navigationName, Action`1 buildAction)
at Connect.Device.DAL.Migrations.Migrations.DeviceContextModelSnapshot.<>c.<BuildModel>b__0_29(EntityTypeBuilder b) in C:\Users\pavelvoronin\Source\Repos\connect.device\Connect.Device.DAL.Migrations\Migrations\DeviceContextModelSnapshot.cs:line 3046
at Microsoft.EntityFrameworkCore.ModelBuilder.Entity(String name, Action`1 buildAction)
at Connect.Device.DAL.Migrations.Migrations.DeviceContextModelSnapshot.BuildModel(ModelBuilder modelBuilder) in C:\Users\pavelvoronin\Source\Repos\connect.device\Connect.Device.DAL.Migrations\Migrations\DeviceContextModelSnapshot.cs:line 3044
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSnapshot.CreateModel()
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSnapshot.get_Model()
at Microsoft.EntityFrameworkCore.Migrations.Design.MigrationsScaffolder.ScaffoldMigration(String migrationName, String rootNamespace, String subNamespace, String language)
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 'Connect.Device.BusinessModel.Values.OrganizationAddress' cannot be configured as non-owned because an owned entity type with the same name already exists.
modelBuilder.Entity("Connect.Device.BusinessModel.Entities.Organization", b =>
{
b.OwnsOne("Connect.Device.BusinessModel.Values.OrganizationAddress", "Address", b1 =>
{
b1.Property<Guid>("OrganizationId");
b1.Property<string>("City")
.HasMaxLength(255);
b1.Property<int>("CountryId");
b1.Property<string>("PostalCode")
.HasMaxLength(50);
b1.Property<string>("Street")
.HasMaxLength(255);
b1.HasKey("OrganizationId");
b1.HasIndex("CountryId");
b1.ToTable("OrganizationAddress");
b1.HasOne("Connect.Device.BusinessModel.Entities.Country")
.WithMany()
.HasForeignKey("CountryId")
.OnDelete(DeleteBehavior.Restrict);
b1.HasOne("Connect.Device.BusinessModel.Entities.Organization")
.WithOne("Address")
.HasForeignKey("Connect.Device.BusinessModel.Values.OrganizationAddress", "OrganizationId")
.OnDelete(DeleteBehavior.Cascade);
b1.OwnsOne("Connect.Device.BusinessModel.Values.House", "House", b2 =>
{
b2.Property<Guid>("OrganizationAddressOrganizationId");
b2.Property<string>("Number")
.HasColumnName("HouseNumber")
.HasMaxLength(50);
b2.Property<string>("Suffix")
.HasColumnName("HouseNumberSuffix")
.HasMaxLength(50);
b2.HasKey("OrganizationAddressOrganizationId");
b2.ToTable("OrganizationAddress");
// line 3093
b2.HasOne("Connect.Device.BusinessModel.Values.OrganizationAddress")
.WithOne("House")
.HasForeignKey("Connect.Device.BusinessModel.Values.House", "OrganizationAddressOrganizationId")
.OnDelete(DeleteBehavior.Cascade);
});
});
And org configuration now looks like this:
public void Configure(EntityTypeBuilder<Organization> builder)
{
builder.ToTable("Organization");
builder.Property(_ => _.Version)
.IsConcurrencyToken()
.HasDefaultValue(0);
builder.OwnsOne(m => m.Address, b =>
{
b.WithOwner().HasForeignKey("OrganizationId");
b.ToTable("OrganizationAddress");
b.HasOne<Country>()
.WithMany()
.HasForeignKey(m => m.CountryId)
.IsRequired()
.OnDelete(DeleteBehavior.Restrict);
b.OwnsOne(
m => m.House,
bld =>
{
bld.Property(m => m.Number).HasColumnName("HouseNumber");
bld.Property(m => m.Suffix).HasColumnName("HouseNumberSuffix");
});
});
builder.OwnsOne(
m => m.ExternalIds,
act => { act.ToTable("OrganizationExternalIds"); });
builder.OwnsOne(
m => m.ExternalReferences,
act => { act.ToTable("OrganizationExternalReferences"); });
builder.Property(m => m.SendInvoiceTo).HasDefaultValue(FulfilmentPartnerSendsInvoiceTo.OurCompany);
}
@voroninp The snapshot issue __is__ a bug: https://github.com/aspnet/EntityFrameworkCore/issues/18183