I have the following model I am creating in EFCore3.1 using the CosmosDb Provider. On trying to run the project and accessing the database for the first time I receive an error:
public class Application
{
public Site Site { get; set; } = new Site();
public Applicant Applicant { get; set; } = new Applicant();
public Agent Agent { get; set; } = new Agent();
}
public class Site
{
public Address Address { get; set; } = new Address();
}
public class Applicant
{
public Address Address { get; set; } = new Address();
}
public class Agent
{
public Address Address { get; set; } = new Address();
}
public class Address
{
public MapCoordinate MapCoordinate { get; set; } = new MapCoordinate();
public GeoLocation GeoLocation { get; set; } = new GeoLocation();
}
In the DbContext I have:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDefaultContainer("Applications");
modelBuilder.Entity<Address>(x => x.Property(y => y.GeoLocation).HasJsonConversion());
modelBuilder.Entity<Application>(x =>
{
x.HasKey(x => x.ApplicationId);
x.HasPartitionKey(x => x.ApplicationId);
x.OwnsOne(x => x.Site).OwnsOne(x => x.Address);
x.OwnsOne(x => x.Applicant).OwnsOne(x => x.Address);
x.OwnsOne(x => x.Agent).OwnsOne(x => x.Address);
});
}
However on the line:
x.OwnsOne(x => x.Site).OwnsOne(x => x.Address);
I get the error:
System.InvalidOperationException: The type 'Address' cannot be marked as owned because a non-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.Metadata.Internal.InternalEntityTypeBuilder.HasOwnership(TypeIdentity& targetEntityType, MemberIdentity navigation, Nullable`1 inverse, ConfigurationSource configurationSource)
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalEntityTypeBuilder.HasOwnership(Type targetEntityType, MemberInfo navigationProperty, ConfigurationSource configurationSource)
at Microsoft.EntityFrameworkCore.Metadata.Builders.OwnedNavigationBuilder`2.OwnsOneBuilder[TNewDependentEntity](MemberIdentity navigation)
at Microsoft.EntityFrameworkCore.Metadata.Builders.OwnedNavigationBuilder`2.OwnsOne[TNewDependentEntity](Expression`1 navigationExpression)
at Planning.Infrastructure.PlanningDbContext.<>c.<OnModelCreating>b__5_1(EntityTypeBuilder`1 x) in C:\dev\Planning\app\src\Planning.Infrastructure\PlanningDbContext.cs:line 29
Please can you advise how I can create a similar json document to the following?:
{
site : { address: { MapCoordinate : blah, GeoLocation: blah },
applicant : { address: { MapCoordinate : blah, GeoLocation: blah },
agent : { address: { MapCoordinate : blah, GeoLocation: blah }
}
EF Core version: 3.1.6
Database provider: Microsoft.EntityFrameworkCore.Cosmos
Target framework: netcoreapp3.1
Operating system: Windows 10
IDE: Visual Studio 2019 Enterprise 16.6.3
modelBuilder.Entity<Address>(x => x.Property(y => y.GeoLocation).HasJsonConversion());
This line configures Address as a regular entity. Hence when you try to configure it as an owned entity it throws. Remove above line from code and configure GeoLocation inside each OwnsOne configuration and you will get a correct model.
Thanks that makes sense. It seems a bit verbose though that I have to duplicate the setup for each implementation of the address. I can see the benefit of being able to do it individually though.
Perhaps it's a feature request? Could the decision around configuring the entity as regular/owned be deferred until a later point? i.e. when using .OwnsOne() in my case thereby allowing configuration of properties on the Type for every usage?
@AndriySvyryd Are we using #6787 to track configuration of all owned-type instances in one place?
@ajcvickers Yes, https://github.com/dotnet/efcore/issues/6787#issuecomment-294047613
@lenniebriscoe Closing this as a duplication of #6787 which covers your request.
@ajcvickers many thanks. It's listed as "punted-for-2.0" and we are on 3.1\5 unless I misunderstand? Does that mean it's not priority right now ?
@lenniebriscoe This is something we definitely plan to do--I would be surprised if it doesn't make it into EF Core 6.0.
Most helpful comment
This line configures
Addressas a regular entity. Hence when you try to configure it as an owned entity it throws. Remove above line from code and configureGeoLocationinside eachOwnsOneconfiguration and you will get a correct model.