Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Owned Shadow Properties: design considerations #1463

Closed
IdeaHunter opened this issue May 8, 2019 · 3 comments
Closed

Owned Shadow Properties: design considerations #1463

IdeaHunter opened this issue May 8, 2019 · 3 comments

Comments

@IdeaHunter
Copy link

I have tried to model a workaroud of not yet implemented feature many-to-many relationship #1368 trough owned shadow properties via fluent api and got an error message that at first sight seems conflict with definition of shadow properties given in documentation.
From documentation about shadow properties

Shadow properties are properties that are not defined in your .NET entity class but are defined for that entity type in the EF Core model.

but the message i've got tells me that shadow property dont have correspoding CLR property.

This leads me to a question:
Is there anything wrong with trying to make a shadow owned properties or im misunderstool the thing i have read in documentation?

Im 100% understand my use case is silly, im just seeing owned properties as a way to do a table splitting and shadow properties as an instrument of keeping underlying EF Core mechanics away from POCO that represents business data and trying to glue then together

More details:

Exception message:
The navigation property 'PropertyRelations' cannot be added to the entity type 'Entity' because there is no corresponding CLR property on the underlying type and navigations properties cannot be added to shadow 
Stack trace:
Microsoft.EntityFrameworkCore.Metadata.Internal.InternalRelationshipBuilder.Navigations(Nullable`1 navigationToPrincipal, Nullable`1 navigationToDependent, EntityType principalEntityType, EntityType dependentEntityType, Nullable`1 configurationSource)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalRelationshipBuilder.Navigations(Nullable`1 navigationToPrincipal, Nullable`1 navigationToDependent, Nullable`1 configurationSource)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalRelationshipBuilder.PrincipalToDependent(String name, ConfigurationSource configurationSource)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalEntityTypeBuilder.Relationship(InternalEntityTypeBuilder targetEntityTypeBuilder, Nullable`1 navigationToTarget, Nullable`1 inverseNavigation, Boolean setTargetAsPrincipal, ConfigurationSource configurationSource, Nullable`1 required)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalEntityTypeBuilder.Owns(TypeIdentity& targetEntityType, PropertyIdentity navigation, Nullable`1 inverse, ConfigurationSource configurationSource)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalEntityTypeBuilder.Owns(Type targetEntityType, String navigationName, ConfigurationSource configurationSource)
   at Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder.OwnsManyBuilder(TypeIdentity& ownedType, String navigationName)
   at Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder.OwnsMany(Type ownedType, String navigationName, Action`1 buildAction)
   at DataAccessLayer.SQL.AppDbContext.OnModelCreating(ModelBuilder modelBuilder)

Steps to reproduce

First i defined shadow property then i tried to use .OwnsMany to model many to many relationship trough helper object. Im using reflection since i have a lot of model that have many to relationship and i personally dont like copy paste approach

var model = modelBuilder.Entity(modelType);

var propType = classProp.PropertyType;
var propName = classProp.Name;

model.Ignore(propName);

var newShadowProp = $"{propName}Relations";
var newShadowPropType = typeof(ICollection<>)
    .MakeGenericType(new[] { typeof(ManyToManyRelation) });

model.Property(newShadowPropType , newShadowProp);

model.OwnsMany(typeof(ManyToManyRelation), newShadowProp, a =>
{
       var tableName = allModelTypes[modelType];
       a.HasForeignKey(nameof(ManyToManyRelation.SourceId));
       a.HasForeignKey(nameof(ManyToManyRelation.TargetId));
       a.HasKey(nameof(ManyToManyRelation.SourceId), nameof(ManyToManyRelation.TargetId));
       a.ToTable($"{tableName}_{classProp.Name}");
}).HasOne(propType)
       .WithMany()
       .HasForeignKey(nameof(ManyToManyRelation.TargetId));

model.HasMany(typeof(ManyToManyRelation), newShadowProp)
      .WithOne()
      .HasForeignKey(nameof(ManyToManyRelation.SourceId));

Further technical details

EF Core version: 2.2.0
Database Provider: Microsoft.EntityFrameworkCore.SqlServer
Operating system: Windows Server 2012 R2
IDE: (e.g. Visual Studio 2017 15.8.9)

@smitpatel
Copy link
Contributor

What you are trying to add is not shadow property but shadow navigation. Shadow navigations are not supported. See #3864

Also your model configuration code has many mistakes.

Leaving this issue open to discuss if we want to update the exception message or documentation to be clearer.

@IdeaHunter
Copy link
Author

IdeaHunter commented May 8, 2019

@smitpatel thanks to pointing to ticket, a change in error message to pinpoint the fact that shadow property and shadow navigation is different kind of beast help understand situation better

Proposing change of error message from(feel free to change it English language is not my primary):

The navigation property 'PropertyName' cannot be added to the entity type 'Entity' because there is no corresponding CLR property on the underlying type and navigations properties cannot be added to shadow

To:

The navigation property 'PropertyName' cannot be added to the entity type 'Entity' because there is no corresponding CLR property on the underlying type and shadow navigation(shadow pointing to another model) currently not supported.

Also im going to create issue in relevant docs.microsoft.com repo for change in documentation to reflect the present limitation and difference between shadow property vs shadow navigation because currently there are clear statement what kind of shadow not supported

Edit: fix quote formatting

@ajcvickers ajcvickers transferred this issue from dotnet/efcore May 10, 2019
@ajcvickers
Copy link
Contributor

ajcvickers commented Sep 2, 2019

Duplicate of #1460

@ajcvickers ajcvickers marked this as a duplicate of #1460 Sep 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants