-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Updates to shared-type entity type handling in proxies #22338
Conversation
@Pilchie RC1 |
|
||
var isPropertyBag = type.IsPropertyBagType(); | ||
IsPropertyBag = isPropertyBag; | ||
HasSharedClrType = isPropertyBag; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cannot be shared, no name was provided
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without this any navigations to the shared type cause it to be discovered as non-shared and hence the many-to-many tests for this will fail. Whatever it is that makes Dictionary work in this case but prevents any other types from working, even if they match the IsPropertyBagType call, needs to be fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then it's a bug in relationship discovery. Shared types shouldn't be discovered in general.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But there is no way to know it's a shared type in relationship discovery, so currently relationship discovery only ignores Dictionary, and there isn't any way to make it ignore any other type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IConventionModel.IsShared
can be used for this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How? The first line of OnModelCreating maps the type as a shared type. That's too late, since relationship discovery has already marked it as not-shared and so this throws.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another way of saying this is that this "Add the specific types used in the tests as shared types in the tests." is what I am trying to make work. If this worked, then I wouldn't be making any product changes in this area.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's too late, since relationship discovery has already marked it as not-shared and so this throws.
That should not happen. Relationship discover discovers by convention configuration source. Fluent API should override that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, then what can be done to fix this? It doesn't currently seem like there is any way to mark an entity type as shared once it has already been marked as non-shared, regardless of configuration source.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
modelBuilder.SharedTypeEntity<MyDict>("SharedDict")
Approved for RC1 pending code review signoff if merged before 10am Pacific on 2020-09-01. |
29785fc
to
001ab5d
Compare
@@ -152,6 +152,8 @@ public ISetSource GetExpectedData() | |||
|
|||
protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) | |||
{ | |||
modelBuilder.SharedTypeEntity<ProxyablePropertyBag>("JoinOneToThreePayloadFullShared"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AndriySvyryd This throws.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then that's a bug
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly! That's what I'm trying to fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, the fix for this should be made in InternalModelBuilder.Entity
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Too late for RC1 now. Will get back to it another time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note if you mean, in UsingEntity
, then doing that without this also throws saying that the type is not configured as a shared-type, which must be explicitly done before calling UsingEntity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dismiss my previous comment. What is the exception that you get without the IsShared change? (Including stacktrace)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The shared type entity type 'JoinOneToThreePayloadFullShared' with clr type 'Microsoft.EntityFrameworkCore.TestModels.ManyToManyModel.ProxyablePropertyBag' cannot be added to the model because a non shared entity type with the same clr type already exists.
System.AggregateException : One or more errors occurred. (The shared type entity type 'JoinOneToThreePayloadFullShared' with clr type 'Microsoft.EntityFrameworkCore.TestModels.ManyToManyModel.ProxyablePropertyBag' cannot be added to the model because a non shared entity type with the same clr type already exists.) (The following constructor parameters did not have matching fixture data: ManyToManyTrackingProxySqlServerFixture fixture)
---- System.InvalidOperationException : The shared type entity type 'JoinOneToThreePayloadFullShared' with clr type 'Microsoft.EntityFrameworkCore.TestModels.ManyToManyModel.ProxyablePropertyBag' cannot be added to the model because a non shared entity type with the same clr type already exists.
---- The following constructor parameters did not have matching fixture data: ManyToManyTrackingProxySqlServerFixture fixture
----- Inner Stack Trace #1 (System.InvalidOperationException) -----
at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.AddEntityType(EntityType entityType) in /home/ajcvickers/efcore/src/EFCore/Metadata/Internal/Model.cs:line 247
at Microsoft.EntityFrameworkCore.Metadata.Internal.Model.AddEntityType(String name, Type type, ConfigurationSource configurationSource) in /home/ajcvickers/efcore/src/EFCore/Metadata/Internal/Model.cs:line 193
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalModelBuilder.Entity(TypeIdentity& type, ConfigurationSource configurationSource, Nullable`1 shouldBeOwned) in /home/ajcvickers/efcore/src/EFCore/Metadata/Internal/InternalModelBuilder.cs:line 185
at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalModelBuilder.SharedTypeEntity(String name, Type type, ConfigurationSource configurationSource, Nullable`1 shouldBeOwned) in /home/ajcvickers/efcore/src/EFCore/Metadata/Internal/InternalModelBuilder.cs:line 67
at Microsoft.EntityFrameworkCore.ModelBuilder.SharedTypeEntity[TEntity](String name) in /home/ajcvickers/efcore/src/EFCore/ModelBuilder.cs:line 158
at Microsoft.EntityFrameworkCore.Query.ManyToManyQueryFixtureBase.OnModelCreating(ModelBuilder modelBuilder, DbContext context) in /home/ajcvickers/efcore/test/EFCore.Specification.Tests/Query/ManyToManyQueryFixtureBase.cs:line 155
at Microsoft.EntityFrameworkCore.ManyToManyTrackingSqlServerTestBase`1.ManyToManyTrackingSqlServerFixtureBase.OnModelCreating(ModelBuilder modelBuilder, DbContext context) in /home/ajcvickers/efcore/test/EFCore.SqlServer.FunctionalTests/ManyToManyTrackingSqlServerTestBase.cs:line 30
at Microsoft.EntityFrameworkCore.TestUtilities.TestModelSource.CreateModel(DbContext context, IConventionSetBuilder conventionSetBuilder, ModelDependencies modelDependencies) in /home/ajcvickers/efcore/test/EFCore.Specification.Tests/TestUtilities/TestModelSource.cs:line 31
at Microsoft.EntityFrameworkCore.Infrastructure.ModelSource.GetModel(DbContext context, IConventionSetBuilder conventionSetBuilder, ModelDependencies modelDependencies) in /home/ajcvickers/efcore/src/EFCore/Infrastructure/ModelSource.cs:line 100
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel() in /home/ajcvickers/efcore/src/EFCore/Internal/DbContextServices.cs:line 84
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model() in /home/ajcvickers/efcore/src/EFCore/Internal/DbContextServices.cs:line 111
at Microsoft.EntityFrameworkCore.Infrastructure.EntityFrameworkServicesBuilder.<>c.<TryAddCoreServices>b__7_3(IServiceProvider p) in /home/ajcvickers/efcore/src/EFCore/Infrastructure/EntityFrameworkServicesBuilder.cs:line 255
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() in /home/ajcvickers/efcore/src/EFCore/DbContext.cs:line 394
at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider() in /home/ajcvickers/efcore/src/EFCore/DbContext.cs:line 376
at Microsoft.EntityFrameworkCore.DbContext.get_ChangeTracker() in /home/ajcvickers/efcore/src/EFCore/DbContext.cs:line 134
at Microsoft.EntityFrameworkCore.ManyToManyTrackingTestBase`1.ManyToManyTrackingFixtureBase.CreateContext() in /home/ajcvickers/efcore/test/EFCore.Specification.Tests/ManyToManyTrackingTestBase.cs:line 3121
at Microsoft.EntityFrameworkCore.TestUtilities.SqlServerTestStore.Initialize(Func`1 createContext, Action`1 seed, Action`1 clean) in /home/ajcvickers/efcore/test/EFCore.SqlServer.FunctionalTests/TestUtilities/SqlServerTestStore.cs:line 93
at Microsoft.EntityFrameworkCore.TestUtilities.TestStore.<>c__DisplayClass13_0.<Initialize>b__0() in /home/ajcvickers/efcore/test/EFCore.Specification.Tests/TestUtilities/TestStore.cs:line 41
at Microsoft.EntityFrameworkCore.TestUtilities.TestStoreIndex.CreateShared(String name, Action initializeDatabase) in /home/ajcvickers/efcore/test/EFCore.Specification.Tests/TestUtilities/TestStoreIndex.cs:line 30
at Microsoft.EntityFrameworkCore.TestUtilities.TestStore.Initialize(IServiceProvider serviceProvider, Func`1 createContext, Action`1 seed, Action`1 clean) in /home/ajcvickers/efcore/test/EFCore.Specification.Tests/TestUtilities/TestStore.cs:line 41
at Microsoft.EntityFrameworkCore.TestUtilities.RelationalTestStore.Initialize(IServiceProvider serviceProvider, Func`1 createContext, Action`1 seed, Action`1 clean) in /home/ajcvickers/efcore/test/EFCore.Relational.Specification.Tests/TestUtilities/RelationalTestStore.cs:line 43
at Microsoft.EntityFrameworkCore.SharedStoreFixtureBase`1..ctor() in /home/ajcvickers/efcore/test/EFCore.Specification.Tests/SharedStoreFixtureBase.cs:line 58
at Microsoft.EntityFrameworkCore.Query.ManyToManyQueryFixtureBase..ctor() in /home/ajcvickers/efcore/test/EFCore.Specification.Tests/Query/ManyToManyQueryFixtureBase.cs:line 15
at Microsoft.EntityFrameworkCore.ManyToManyTrackingTestBase`1.ManyToManyTrackingFixtureBase..ctor() in /home/ajcvickers/efcore/test/EFCore.Specification.Tests/ManyToManyTrackingTestBase.cs:line 3126
at Microsoft.EntityFrameworkCore.ManyToManyTrackingSqlServerTestBase`1.ManyToManyTrackingSqlServerFixtureBase..ctor()
at Microsoft.EntityFrameworkCore.ManyToManyTrackingProxySqlServerTest.ManyToManyTrackingProxySqlServerFixture..ctor() in /home/ajcvickers/efcore/test/EFCore.SqlServer.FunctionalTests/ManyToManyTrackingProxySqlServerTest.cs:line 21
----- Inner Stack Trace #2 (Xunit.Sdk.TestClassException) -----
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. It probably needs a convention scope around most of the InternalModelBuilder.Entity body to avoid the type being readded as non shared before it's added as shared
Clearing approval since we passed the deadline. Please re-add |
@@ -402,6 +402,9 @@ | |||
<data name="EntityTypeNotFound" xml:space="preserve"> | |||
<value>The entity type '{entityType}' was not found. Ensure that the entity type has been added to the model.</value> | |||
</data> | |||
<data name="EntityTypeNotFoundSharedProxy" xml:space="preserve"> | |||
<value>The type '{clrType}' is configured as a shared-type entity type, but the entity type name is not known. Ensure that CreateProxy is called on a DbSet created specifically for the shared-type entity type through use of a `DbContext.Set` overload that accepts an entity type name.</value> | |||
</data> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move to ProxiesStrings.resx
Fixes #22337
See also #22336