diff --git a/src/EFCore/Infrastructure/ModelValidator.cs b/src/EFCore/Infrastructure/ModelValidator.cs index 3c898a19d94..4aaafd6b5b4 100644 --- a/src/EFCore/Infrastructure/ModelValidator.cs +++ b/src/EFCore/Infrastructure/ModelValidator.cs @@ -1104,12 +1104,15 @@ protected virtual void ValidateData([NotNull] IModel model, [NotNull] IDiagnosti keyValues[i] = seedDatum[key.Properties[i].Name]; } - foreach (var navigation in entityType.GetNavigations()) + foreach (var navigation in entityType.GetNavigations().Concat(entityType.GetSkipNavigations())) { if (seedDatum.TryGetValue(navigation.Name, out var value) && ((navigation.IsCollection && value is IEnumerable collection && collection.Any()) || (!navigation.IsCollection && value != null))) { + var foreignKey = navigation is INavigation nav + ? nav.ForeignKey + : ((ISkipNavigation)navigation).ForeignKey; if (sensitiveDataLogged) { throw new InvalidOperationException( @@ -1117,16 +1120,16 @@ protected virtual void ValidateData([NotNull] IModel model, [NotNull] IDiagnosti entityType.DisplayName(), string.Join(", ", key.Properties.Select((p, i) => p.Name + ":" + keyValues[i])), navigation.Name, - navigation.TargetEntityType.DisplayName(), - navigation.ForeignKey.Properties.Format())); + foreignKey.DeclaringEntityType.DisplayName(), + foreignKey.Properties.Format())); } throw new InvalidOperationException( CoreStrings.SeedDatumNavigation( entityType.DisplayName(), navigation.Name, - navigation.TargetEntityType.DisplayName(), - navigation.ForeignKey.Properties.Format())); + foreignKey.DeclaringEntityType.DisplayName(), + foreignKey.Properties.Format())); } } diff --git a/src/EFCore/Metadata/Internal/EntityType.cs b/src/EFCore/Metadata/Internal/EntityType.cs index 7233917b70e..d76dd0f2d85 100644 --- a/src/EFCore/Metadata/Internal/EntityType.cs +++ b/src/EFCore/Metadata/Internal/EntityType.cs @@ -2944,7 +2944,10 @@ public virtual IEnumerable> GetSeedData(bool provide var data = new List>(); var valueConverters = new Dictionary(StringComparer.Ordinal); - var properties = this.GetPropertiesAndNavigations().ToDictionary(p => p.Name); + var properties = GetProperties() + .Concat(GetNavigations()) + .Concat(GetSkipNavigations()) + .ToDictionary(p => p.Name); foreach (var rawSeed in _data) { var seed = new Dictionary(StringComparer.Ordinal); @@ -2958,13 +2961,10 @@ public virtual IEnumerable> GetSeedData(bool provide { ValueConverter valueConverter = null; if (providerValues + && propertyBase is IProperty property && !valueConverters.TryGetValue(propertyBase.Name, out valueConverter)) { - if (propertyBase is IProperty property) - { - valueConverter = property.GetTypeMapping().Converter; - } - + valueConverter = property.GetTypeMapping().Converter; valueConverters[propertyBase.Name] = valueConverter; } diff --git a/src/EFCore/Properties/CoreStrings.Designer.cs b/src/EFCore/Properties/CoreStrings.Designer.cs index afe9c065ba6..ea842ac919b 100644 --- a/src/EFCore/Properties/CoreStrings.Designer.cs +++ b/src/EFCore/Properties/CoreStrings.Designer.cs @@ -2334,7 +2334,7 @@ public static string SeedDatumMissingValue([CanBeNull] object entityType, [CanBe entityType, property); /// - /// The seed entity for entity type '{entityType}' cannot be added because it has the navigation '{navigation}' set. To seed relationships, add the related entity seed to '{relatedEntityType}' and specify the foreign key values {foreignKeyProperties}. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the involved property values. + /// The seed entity for entity type '{entityType}' cannot be added because it has the navigation '{navigation}' set. To seed relationships, add the entity seed to '{relatedEntityType}' and specify the foreign key values {foreignKeyProperties}. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the involved property values. /// public static string SeedDatumNavigation([CanBeNull] object entityType, [CanBeNull] object navigation, [CanBeNull] object relatedEntityType, [CanBeNull] object foreignKeyProperties) => string.Format( @@ -2342,7 +2342,7 @@ public static string SeedDatumNavigation([CanBeNull] object entityType, [CanBeNu entityType, navigation, relatedEntityType, foreignKeyProperties); /// - /// The seed entity for entity type '{entityType}' with the key value '{keyValue}' cannot be added because it has the navigation '{navigation}' set. To seed relationships, add the related entity seed to '{relatedEntityType}' and specify the foreign key values {foreignKeyProperties}. + /// The seed entity for entity type '{entityType}' with the key value '{keyValue}' cannot be added because it has the navigation '{navigation}' set. To seed relationships, add the entity seed to '{relatedEntityType}' and specify the foreign key values {foreignKeyProperties}. /// public static string SeedDatumNavigationSensitive([CanBeNull] object entityType, [CanBeNull] object keyValue, [CanBeNull] object navigation, [CanBeNull] object relatedEntityType, [CanBeNull] object foreignKeyProperties) => string.Format( diff --git a/src/EFCore/Properties/CoreStrings.resx b/src/EFCore/Properties/CoreStrings.resx index cdad1deef94..34943f46ce4 100644 --- a/src/EFCore/Properties/CoreStrings.resx +++ b/src/EFCore/Properties/CoreStrings.resx @@ -1302,10 +1302,10 @@ The seed entity for entity type '{entityType}' cannot be added because no value was provided for the required property '{property}'. - The seed entity for entity type '{entityType}' cannot be added because it has the navigation '{navigation}' set. To seed relationships, add the related entity seed to '{relatedEntityType}' and specify the foreign key values {foreignKeyProperties}. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the involved property values. + The seed entity for entity type '{entityType}' cannot be added because it has the navigation '{navigation}' set. To seed relationships, add the entity seed to '{relatedEntityType}' and specify the foreign key values {foreignKeyProperties}. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the involved property values. - The seed entity for entity type '{entityType}' with the key value '{keyValue}' cannot be added because it has the navigation '{navigation}' set. To seed relationships, add the related entity seed to '{relatedEntityType}' and specify the foreign key values {foreignKeyProperties}. + The seed entity for entity type '{entityType}' with the key value '{keyValue}' cannot be added because it has the navigation '{navigation}' set. To seed relationships, add the entity seed to '{relatedEntityType}' and specify the foreign key values {foreignKeyProperties}. The seed entity for entity type '{entityType}' cannot be added because a non-zero value is required for property '{property}'. Consider providing a negative value to avoid collisions with non-seed data. diff --git a/test/EFCore.Tests/Infrastructure/ModelValidatorTest.cs b/test/EFCore.Tests/Infrastructure/ModelValidatorTest.cs index 7314a42d9bc..b4bdd1ac72d 100644 --- a/test/EFCore.Tests/Infrastructure/ModelValidatorTest.cs +++ b/test/EFCore.Tests/Infrastructure/ModelValidatorTest.cs @@ -1212,6 +1212,37 @@ public virtual void Detects_reference_navigations_in_seeds(bool sensitiveDataLog modelBuilder.Model); } + [ConditionalTheory] + [InlineData(true)] + [InlineData(false)] + public virtual void Detects_reference_navigations_in_seeds2(bool sensitiveDataLoggingEnabled) + { + var modelBuilder = CreateConventionalModelBuilder(sensitiveDataLoggingEnabled); + modelBuilder.Entity( + e => + { + e.HasMany(o => o.Products) + .WithMany(p => p.Orders); + e.HasData( + new Order { Id = 1, Products = new List { new Product() } }); + }); + + VerifyError( + sensitiveDataLoggingEnabled + ? CoreStrings.SeedDatumNavigationSensitive( + nameof(Order), + $"{nameof(Order.Id)}:1", + nameof(Order.Products), + "OrderProduct (Dictionary)", + "{'OrdersId'}") + : CoreStrings.SeedDatumNavigation( + nameof(Order), + nameof(Order.Products), + "OrderProduct (Dictionary)", + "{'OrdersId'}"), + modelBuilder.Model); + } + [ConditionalTheory] [InlineData(true)] [InlineData(false)]