diff --git a/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs index 05b56c7ebda..e53268591c4 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs @@ -11,19 +11,14 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures the discriminator value for entity types as the entity type name. /// public class CosmosDiscriminatorConvention : DiscriminatorConvention, IEntityTypeAddedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public CosmosDiscriminatorConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) : base(dependencies) { diff --git a/src/EFCore.Cosmos/Metadata/Conventions/StoreKeyConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/StoreKeyConvention.cs index 41bb656fbc5..24c7ea6bbb3 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/StoreKeyConvention.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/StoreKeyConvention.cs @@ -12,6 +12,14 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Conventions { + /// + /// + /// A convention that adds the 'id' property - a key required by Azure Cosmos. + /// + /// This convention also add the '__jObject' containing the JSON object returned by the store. + /// + /// + /// public class StoreKeyConvention : IEntityTypeAddedConvention, IForeignKeyOwnershipChangedConvention, @@ -21,6 +29,10 @@ public class StoreKeyConvention : public static readonly string IdPropertyName = "id"; public static readonly string JObjectPropertyName = "__jObject"; + /// + /// Creates a new instance of . + /// + /// Parameter object containing dependencies for this convention. public StoreKeyConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs b/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs index 691aeee5d32..a219bb011b0 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CSharpDbContextGenerator.cs @@ -7,7 +7,6 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; using Microsoft.EntityFrameworkCore.Design; -using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; @@ -32,7 +31,6 @@ public class CSharpDbContextGenerator : ICSharpDbContextGenerator private readonly ICSharpHelper _code; private readonly IProviderConfigurationCodeGenerator _providerConfigurationCodeGenerator; private readonly IAnnotationCodeGenerator _annotationCodeGenerator; - private readonly LoggingDefinitions _loggingDefinitions; private IndentedStringBuilder _sb; private bool _entityTypeBuilderInitialized; @@ -45,18 +43,15 @@ public class CSharpDbContextGenerator : ICSharpDbContextGenerator public CSharpDbContextGenerator( [NotNull] IProviderConfigurationCodeGenerator providerConfigurationCodeGenerator, [NotNull] IAnnotationCodeGenerator annotationCodeGenerator, - [NotNull] ICSharpHelper cSharpHelper, - [NotNull] LoggingDefinitions loggingDefinitions) + [NotNull] ICSharpHelper cSharpHelper) { Check.NotNull(providerConfigurationCodeGenerator, nameof(providerConfigurationCodeGenerator)); Check.NotNull(annotationCodeGenerator, nameof(annotationCodeGenerator)); Check.NotNull(cSharpHelper, nameof(cSharpHelper)); - Check.NotNull(loggingDefinitions, nameof(loggingDefinitions)); _providerConfigurationCodeGenerator = providerConfigurationCodeGenerator; _annotationCodeGenerator = annotationCodeGenerator; _code = cSharpHelper; - _loggingDefinitions = loggingDefinitions; } /// @@ -463,9 +458,9 @@ private void GenerateKey(IKey key, IEntityType entityType, bool useDataAnnotatio { if (key is Key concreteKey && key.Properties.SequenceEqual( - new KeyDiscoveryConvention(null).DiscoverKeyProperties( + KeyDiscoveryConvention.DiscoverKeyProperties( concreteKey.DeclaringEntityType, - concreteKey.DeclaringEntityType.GetProperties().ToList()))) + concreteKey.DeclaringEntityType.GetProperties()))) { return; } @@ -690,7 +685,7 @@ private void GenerateProperty(IProperty property, bool useDataAnnotations) var valueGenerated = property.ValueGenerated; var isRowVersion = false; if (((IConventionProperty)property).GetValueGeneratedConfigurationSource().HasValue - && RelationalValueGeneratorConvention.GetValueGenerated(property) != valueGenerated) + && RelationalValueGenerationConvention.GetValueGenerated(property) != valueGenerated) { string methodName; switch (valueGenerated) diff --git a/src/EFCore.Design/Scaffolding/Internal/CSharpEntityTypeGenerator.cs b/src/EFCore.Design/Scaffolding/Internal/CSharpEntityTypeGenerator.cs index 0e623774adb..b99e7464e36 100644 --- a/src/EFCore.Design/Scaffolding/Internal/CSharpEntityTypeGenerator.cs +++ b/src/EFCore.Design/Scaffolding/Internal/CSharpEntityTypeGenerator.cs @@ -230,13 +230,12 @@ protected virtual void GeneratePropertyDataAnnotations( private void GenerateKeyAttribute(IProperty property) { - var key = property.AsProperty().PrimaryKey; - + var key = property.FindContainingPrimaryKey(); if (key?.Properties.Count == 1) { - if (key is Key concreteKey - && key.Properties.SequenceEqual(new KeyDiscoveryConvention(null).DiscoverKeyProperties( - concreteKey.DeclaringEntityType, concreteKey.DeclaringEntityType.GetProperties().ToList()))) + if (key is IConventionKey concreteKey + && key.Properties.SequenceEqual(KeyDiscoveryConvention.DiscoverKeyProperties( + concreteKey.DeclaringEntityType, concreteKey.DeclaringEntityType.GetProperties()))) { return; } diff --git a/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs b/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs index 58d46ae6a00..e68c42a33ad 100644 --- a/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs +++ b/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs @@ -513,7 +513,7 @@ protected virtual KeyBuilder VisitPrimaryKey([NotNull] EntityTypeBuilder builder var property = builder.Metadata.FindProperty(GetPropertyName(primaryKey.Columns[0]))?.AsProperty(); if (property != null) { - var conventionalValueGenerated = RelationalValueGeneratorConvention.GetValueGenerated(property); + var conventionalValueGenerated = RelationalValueGenerationConvention.GetValueGenerated(property); if (conventionalValueGenerated == ValueGenerated.OnAdd) { property.ValueGenerated = ValueGenerated.Never; diff --git a/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs b/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs index 9503be768dd..79722a64705 100644 --- a/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs +++ b/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs @@ -150,7 +150,9 @@ protected virtual void ValidateDefaultValuesOnKeys([NotNull] IModel model, [NotN /// /// The model to validate. /// The logger to use. - protected virtual void ValidateSharedTableCompatibility([NotNull] IModel model, [NotNull] IDiagnosticsLogger logger) + protected virtual void ValidateSharedTableCompatibility( + [NotNull] IModel model, + [NotNull] IDiagnosticsLogger logger) { var tables = new Dictionary>(); foreach (var entityType in model.GetEntityTypes().Where(et => et.FindPrimaryKey() != null)) @@ -286,7 +288,8 @@ private static bool IsIdentifyingPrincipal(IEntityType dependentEntityType, IEnt /// The table name. /// The logger to use. protected virtual void ValidateSharedColumnsCompatibility( - [NotNull] IReadOnlyList mappedTypes, [NotNull] string tableName, [NotNull] IDiagnosticsLogger logger) + [NotNull] IReadOnlyList mappedTypes, [NotNull] string tableName, + [NotNull] IDiagnosticsLogger logger) { Dictionary storeConcurrencyTokens = null; if (mappedTypes.Count > 1) @@ -418,7 +421,8 @@ protected virtual void ValidateSharedColumnsCompatibility( { foreach (var missingColumn in missingConcurrencyTokens) { - if (!entityType.GetAllBaseTypes().SelectMany(t => t.GetDeclaredProperties()).Any(p => p.GetColumnName() == missingColumn)) + if (entityType.GetAllBaseTypes().SelectMany(t => t.GetDeclaredProperties()) + .All(p => p.GetColumnName() != missingColumn)) { throw new InvalidOperationException( RelationalStrings.MissingConcurrencyColumn(entityType.DisplayName(), missingColumn, tableName)); diff --git a/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs b/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs index cee3ec2951a..fe311c5fe3c 100644 --- a/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs +++ b/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs @@ -59,12 +59,12 @@ public override ConventionSet CreateConventionSet() { var conventionSet = base.CreateConventionSet(); - ValueGeneratorConvention valueGeneratorConvention = new RelationalValueGeneratorConvention(Dependencies, RelationalDependencies); + ValueGenerationConvention valueGenerationConvention = new RelationalValueGenerationConvention(Dependencies, RelationalDependencies); - ReplaceConvention(conventionSet.EntityTypeBaseTypeChangedConventions, valueGeneratorConvention); - ReplaceConvention(conventionSet.EntityTypePrimaryKeyChangedConventions, valueGeneratorConvention); - ReplaceConvention(conventionSet.ForeignKeyAddedConventions, valueGeneratorConvention); - ReplaceConvention(conventionSet.ForeignKeyRemovedConventions, valueGeneratorConvention); + ReplaceConvention(conventionSet.EntityTypeBaseTypeChangedConventions, valueGenerationConvention); + ReplaceConvention(conventionSet.EntityTypePrimaryKeyChangedConventions, valueGenerationConvention); + ReplaceConvention(conventionSet.ForeignKeyAddedConventions, valueGenerationConvention); + ReplaceConvention(conventionSet.ForeignKeyRemovedConventions, valueGenerationConvention); var relationalColumnAttributeConvention = new RelationalColumnAttributeConvention(Dependencies, RelationalDependencies); @@ -75,7 +75,7 @@ public override ConventionSet CreateConventionSet() conventionSet.EntityTypeBaseTypeChangedConventions.Add(new TableNameFromDbSetConvention(Dependencies, RelationalDependencies)); conventionSet.PropertyFieldChangedConventions.Add(relationalColumnAttributeConvention); conventionSet.PropertyAnnotationChangedConventions.Add(storeGenerationConvention); - conventionSet.PropertyAnnotationChangedConventions.Add((RelationalValueGeneratorConvention)valueGeneratorConvention); + conventionSet.PropertyAnnotationChangedConventions.Add((RelationalValueGenerationConvention)valueGenerationConvention); var sharedTableConvention = new SharedTableConvention(Dependencies, RelationalDependencies); ConventionSet.AddBefore( diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalColumnAttributeConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalColumnAttributeConvention.cs index ee24bbe5339..7e301737fe9 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalColumnAttributeConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalColumnAttributeConvention.cs @@ -10,19 +10,15 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures column name and type for a property based on the applied . /// - public class RelationalColumnAttributeConvention : PropertyAttributeConvention + public class RelationalColumnAttributeConvention : PropertyAttributeConventionBase { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. + /// Parameter object containing relational dependencies for this convention. public RelationalColumnAttributeConvention( [NotNull] ProviderConventionSetBuilderDependencies dependencies, [NotNull] RelationalConventionSetBuilderDependencies relationalDependencies) @@ -31,13 +27,17 @@ public RelationalColumnAttributeConvention( } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called after a property is added to the entity type with an attribute on the associated CLR property or field. /// + /// The builder for the property. + /// The attribute. + /// The member that has the attribute. + /// Additional information associated with convention execution. protected override void ProcessPropertyAdded( - IConventionPropertyBuilder propertyBuilder, ColumnAttribute attribute, MemberInfo clrMember, IConventionContext context) + IConventionPropertyBuilder propertyBuilder, + ColumnAttribute attribute, + MemberInfo clrMember, + IConventionContext context) { if (!string.IsNullOrWhiteSpace(attribute.Name)) { diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalDbFunctionConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalDbFunctionConvention.cs index fa1551ca3cb..e0acd9874a5 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalDbFunctionConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalDbFunctionConvention.cs @@ -12,19 +12,16 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures the name and schema for a based on the applied + /// . /// public class RelationalDbFunctionConvention : IModelAnnotationChangedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. + /// Parameter object containing relational dependencies for this convention. public RelationalDbFunctionConvention( [NotNull] ProviderConventionSetBuilderDependencies dependencies, [NotNull] RelationalConventionSetBuilderDependencies relationalDependencies) diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalMaxIdentifierLengthConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalMaxIdentifierLengthConvention.cs index 3f0285cf64c..f2e24606e28 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalMaxIdentifierLengthConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalMaxIdentifierLengthConvention.cs @@ -8,19 +8,16 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures the maximum object identifier length supported by the database. /// public class RelationalMaxIdentifierLengthConvention : IModelInitializedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// The maximum object identifier length supported by the database. + /// Parameter object containing dependencies for this convention. + /// Parameter object containing relational dependencies for this convention. public RelationalMaxIdentifierLengthConvention( int maxIdentifierLength, [NotNull] ProviderConventionSetBuilderDependencies dependencies, diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalTableAttributeConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalTableAttributeConvention.cs index 5935dc737ee..e0f8d9c3966 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalTableAttributeConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalTableAttributeConvention.cs @@ -9,19 +9,15 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures the table name and schema for entity types based on the applied . /// - public class RelationalTableAttributeConvention : EntityTypeAttributeConvention + public class RelationalTableAttributeConvention : EntityTypeAttributeConventionBase { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. + /// Parameter object containing relational dependencies for this convention. public RelationalTableAttributeConvention( [NotNull] ProviderConventionSetBuilderDependencies dependencies, [NotNull] RelationalConventionSetBuilderDependencies relationalDependencies) @@ -30,11 +26,11 @@ public RelationalTableAttributeConvention( } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called after an entity type is added to the model if it has an attribute. /// + /// The builder for the entity type. + /// The attribute. + /// Additional information associated with convention execution. protected override void ProcessEntityTypeAdded( IConventionEntityTypeBuilder entityTypeBuilder, TableAttribute attribute, @@ -44,8 +40,7 @@ protected override void ProcessEntityTypeAdded( { entityTypeBuilder.ToTable(attribute.Name, attribute.Schema, fromDataAnnotation: true); } - - if (!string.IsNullOrWhiteSpace(attribute.Name)) + else if (!string.IsNullOrWhiteSpace(attribute.Name)) { entityTypeBuilder.ToTable(attribute.Name, fromDataAnnotation: true); } diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalValueGeneratorConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalValueGenerationConvention.cs similarity index 73% rename from src/EFCore.Relational/Metadata/Conventions/RelationalValueGeneratorConvention.cs rename to src/EFCore.Relational/Metadata/Conventions/RelationalValueGenerationConvention.cs index e6af9bbdb0e..6ed0e626f5c 100644 --- a/src/EFCore.Relational/Metadata/Conventions/RelationalValueGeneratorConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/RelationalValueGenerationConvention.cs @@ -8,20 +8,18 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures store value generation as on properties that are + /// part of the primary key and not part of any foreign keys or were configured to have a database default value. + /// It also configures properties as if they were configured as computed columns. /// - public class RelationalValueGeneratorConvention : ValueGeneratorConvention, IPropertyAnnotationChangedConvention + public class RelationalValueGenerationConvention : ValueGenerationConvention, IPropertyAnnotationChangedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// - public RelationalValueGeneratorConvention( + /// Parameter object containing dependencies for this convention. + /// Parameter object containing relational dependencies for this convention. + public RelationalValueGenerationConvention( [NotNull] ProviderConventionSetBuilderDependencies dependencies, [NotNull] RelationalConventionSetBuilderDependencies relationalDependencies) : base(dependencies) @@ -69,7 +67,7 @@ public virtual void ProcessPropertyAnnotationChanged( /// The store value generation strategy to set for the given property. public static new ValueGenerated? GetValueGenerated([NotNull] IProperty property) { - var valueGenerated = ValueGeneratorConvention.GetValueGenerated(property); + var valueGenerated = ValueGenerationConvention.GetValueGenerated(property); if (valueGenerated != null) { return valueGenerated; diff --git a/src/EFCore.Relational/Metadata/Conventions/SharedTableConvention.cs b/src/EFCore.Relational/Metadata/Conventions/SharedTableConvention.cs index 2c20b39e8c4..00f553c4cfb 100644 --- a/src/EFCore.Relational/Metadata/Conventions/SharedTableConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/SharedTableConvention.cs @@ -14,19 +14,15 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that manipulates names of database objects for entity types that share a table to avoid clashes. /// public class SharedTableConvention : IModelFinalizedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. + /// Parameter object containing relational dependencies for this convention. public SharedTableConvention( [NotNull] ProviderConventionSetBuilderDependencies dependencies, [NotNull] RelationalConventionSetBuilderDependencies relationalDependencies) diff --git a/src/EFCore.Relational/Metadata/Conventions/StoreGenerationConvention.cs b/src/EFCore.Relational/Metadata/Conventions/StoreGenerationConvention.cs index d45e7ca81d4..7505e1b72b1 100644 --- a/src/EFCore.Relational/Metadata/Conventions/StoreGenerationConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/StoreGenerationConvention.cs @@ -10,19 +10,15 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that ensures that properties aren't configured to have a default value and as computed column at the same time. /// public class StoreGenerationConvention : IPropertyAnnotationChangedConvention, IModelFinalizedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. + /// Parameter object containing relational dependencies for this convention. public StoreGenerationConvention( [NotNull] ProviderConventionSetBuilderDependencies dependencies, [NotNull] RelationalConventionSetBuilderDependencies relationalDependencies) diff --git a/src/EFCore.Relational/Metadata/Conventions/TableNameFromDbSetConvention.cs b/src/EFCore.Relational/Metadata/Conventions/TableNameFromDbSetConvention.cs index 8d5bef19fde..ad82d21dc22 100644 --- a/src/EFCore.Relational/Metadata/Conventions/TableNameFromDbSetConvention.cs +++ b/src/EFCore.Relational/Metadata/Conventions/TableNameFromDbSetConvention.cs @@ -11,21 +11,17 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures the table name based on the property name. /// public class TableNameFromDbSetConvention : IEntityTypeBaseTypeChangedConvention { private readonly IDictionary _sets; /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. + /// Parameter object containing relational dependencies for this convention. public TableNameFromDbSetConvention( [NotNull] ProviderConventionSetBuilderDependencies dependencies, [NotNull] RelationalConventionSetBuilderDependencies relationalDependencies) diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs index c6bcbd62b4d..3ab995d4615 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs @@ -48,26 +48,26 @@ public override ConventionSet CreateConventionSet() { var conventionSet = base.CreateConventionSet(); - var valueGenerationStrategyConvention = new SqlServerValueGenerationStrategyConvention(Dependencies); + var valueGenerationStrategyConvention = new SqlServerValueGenerationStrategyConvention(Dependencies, RelationalDependencies); conventionSet.ModelInitializedConventions.Add(valueGenerationStrategyConvention); conventionSet.ModelInitializedConventions.Add( new RelationalMaxIdentifierLengthConvention(128, Dependencies, RelationalDependencies)); - ValueGeneratorConvention valueGeneratorConvention = new SqlServerValueGeneratorConvention(Dependencies, RelationalDependencies); - ReplaceConvention(conventionSet.EntityTypeBaseTypeChangedConventions, valueGeneratorConvention); + ValueGenerationConvention valueGenerationConvention = new SqlServerValueGenerationConvention(Dependencies, RelationalDependencies); + ReplaceConvention(conventionSet.EntityTypeBaseTypeChangedConventions, valueGenerationConvention); - var sqlServerInMemoryTablesConvention = new SqlServerMemoryOptimizedTablesConvention(Dependencies); + var sqlServerInMemoryTablesConvention = new SqlServerMemoryOptimizedTablesConvention(Dependencies, RelationalDependencies); conventionSet.EntityTypeAnnotationChangedConventions.Add(sqlServerInMemoryTablesConvention); - ReplaceConvention(conventionSet.EntityTypePrimaryKeyChangedConventions, valueGeneratorConvention); + ReplaceConvention(conventionSet.EntityTypePrimaryKeyChangedConventions, valueGenerationConvention); conventionSet.KeyAddedConventions.Add(sqlServerInMemoryTablesConvention); - ReplaceConvention(conventionSet.ForeignKeyAddedConventions, valueGeneratorConvention); + ReplaceConvention(conventionSet.ForeignKeyAddedConventions, valueGenerationConvention); - ReplaceConvention(conventionSet.ForeignKeyRemovedConventions, valueGeneratorConvention); + ReplaceConvention(conventionSet.ForeignKeyRemovedConventions, valueGenerationConvention); - var sqlServerIndexConvention = new SqlServerIndexConvention(Dependencies, _sqlGenerationHelper); + var sqlServerIndexConvention = new SqlServerIndexConvention(Dependencies, RelationalDependencies, _sqlGenerationHelper); conventionSet.EntityTypeBaseTypeChangedConventions.Add(sqlServerIndexConvention); @@ -90,7 +90,7 @@ public override ConventionSet CreateConventionSet() conventionSet.PropertyAnnotationChangedConventions.Add(sqlServerIndexConvention); ReplaceConvention(conventionSet.PropertyAnnotationChangedConventions, storeGenerationConvention); ReplaceConvention( - conventionSet.PropertyAnnotationChangedConventions, (RelationalValueGeneratorConvention)valueGeneratorConvention); + conventionSet.PropertyAnnotationChangedConventions, (RelationalValueGenerationConvention)valueGenerationConvention); ReplaceConvention( conventionSet.ModelAnnotationChangedConventions, diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerDbFunctionConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerDbFunctionConvention.cs index a1c8df3cbc9..73a0d2688ce 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerDbFunctionConvention.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerDbFunctionConvention.cs @@ -10,19 +10,16 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures the name and schema for a based on the applied + /// and the default schema as 'dbo'. /// public class SqlServerDbFunctionConvention : RelationalDbFunctionConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. + /// Parameter object containing relational dependencies for this convention. public SqlServerDbFunctionConvention( [NotNull] ProviderConventionSetBuilderDependencies dependencies, [NotNull] RelationalConventionSetBuilderDependencies relationalDependencies) diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerIndexConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerIndexConvention.cs index 6c3f5bdd9db..2123a0a1edc 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerIndexConvention.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerIndexConvention.cs @@ -13,10 +13,8 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures the filter for unique non-clustered indexes with nullable columns + /// to filter out null values. /// public class SqlServerIndexConvention : IEntityTypeBaseTypeChangedConvention, @@ -29,13 +27,15 @@ public class SqlServerIndexConvention : private readonly ISqlGenerationHelper _sqlGenerationHelper; /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. + /// Parameter object containing relational dependencies for this convention. + /// SQL command generation helper service. public SqlServerIndexConvention( - [NotNull] ProviderConventionSetBuilderDependencies dependencies, [NotNull] ISqlGenerationHelper sqlGenerationHelper) + [NotNull] ProviderConventionSetBuilderDependencies dependencies, + [NotNull] RelationalConventionSetBuilderDependencies relationalDependencies, + [NotNull] ISqlGenerationHelper sqlGenerationHelper) { _sqlGenerationHelper = sqlGenerationHelper; Dependencies = dependencies; @@ -149,7 +149,6 @@ public virtual void ProcessPropertyAnnotationChanged( private IConventionIndexBuilder SetIndexFilter(IConventionIndexBuilder indexBuilder, bool columnNameChanged = false) { - // TODO: compare with a cached filter to avoid overriding if it was set by a different convention var index = indexBuilder.Metadata; if (index.IsUnique && index.GetSqlServerIsClustered() != true diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerMemoryOptimizedTablesConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerMemoryOptimizedTablesConvention.cs index 8eef7ed1821..b329e2e75e9 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerMemoryOptimizedTablesConvention.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerMemoryOptimizedTablesConvention.cs @@ -11,10 +11,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures indexes as non-clustered for memory-optimized tables. /// public class SqlServerMemoryOptimizedTablesConvention : IEntityTypeAnnotationChangedConvention, @@ -22,12 +19,13 @@ public class SqlServerMemoryOptimizedTablesConvention : IIndexAddedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// - public SqlServerMemoryOptimizedTablesConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) + /// Parameter object containing dependencies for this convention. + /// Parameter object containing relational dependencies for this convention. + public SqlServerMemoryOptimizedTablesConvention( + [NotNull] ProviderConventionSetBuilderDependencies dependencies, + [NotNull] RelationalConventionSetBuilderDependencies relationalDependencies) { Dependencies = dependencies; } @@ -46,8 +44,11 @@ public SqlServerMemoryOptimizedTablesConvention([NotNull] ProviderConventionSetB /// The old annotation. /// Additional information associated with convention execution. public virtual void ProcessEntityTypeAnnotationChanged( - IConventionEntityTypeBuilder entityTypeBuilder, string name, IConventionAnnotation annotation, - IConventionAnnotation oldAnnotation, IConventionContext context) + IConventionEntityTypeBuilder entityTypeBuilder, + string name, + IConventionAnnotation annotation, + IConventionAnnotation oldAnnotation, + IConventionContext context) { if (name == SqlServerAnnotationNames.MemoryOptimized) { diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerStoreGenerationConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerStoreGenerationConvention.cs index 25cc2e124a7..25e2dcf6e59 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerStoreGenerationConvention.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerStoreGenerationConvention.cs @@ -12,19 +12,16 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that ensures that properties aren't configured to have a default value, as computed column + /// or using a at the same time. /// public class SqlServerStoreGenerationConvention : StoreGenerationConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. + /// Parameter object containing relational dependencies for this convention. public SqlServerStoreGenerationConvention( [NotNull] ProviderConventionSetBuilderDependencies dependencies, [NotNull] RelationalConventionSetBuilderDependencies relationalDependencies) @@ -41,7 +38,10 @@ public SqlServerStoreGenerationConvention( /// The old annotation. /// Additional information associated with convention execution. public override void ProcessPropertyAnnotationChanged( - IConventionPropertyBuilder propertyBuilder, string name, IConventionAnnotation annotation, IConventionAnnotation oldAnnotation, + IConventionPropertyBuilder propertyBuilder, + string name, + IConventionAnnotation annotation, + IConventionAnnotation oldAnnotation, IConventionContext context) { if (annotation == null diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGeneratorConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationConvention.cs similarity index 73% rename from src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGeneratorConvention.cs rename to src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationConvention.cs index e88443d59e4..e3f432e65b4 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGeneratorConvention.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationConvention.cs @@ -10,20 +10,19 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures store value generation as on properties that are + /// part of the primary key and not part of any foreign keys, were configured to have a database default value + /// or were configured to use a . + /// It also configures properties as if they were configured as computed columns. /// - public class SqlServerValueGeneratorConvention : RelationalValueGeneratorConvention + public class SqlServerValueGenerationConvention : RelationalValueGenerationConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// - public SqlServerValueGeneratorConvention( + /// Parameter object containing dependencies for this convention. + /// Parameter object containing relational dependencies for this convention. + public SqlServerValueGenerationConvention( [NotNull] ProviderConventionSetBuilderDependencies dependencies, [NotNull] RelationalConventionSetBuilderDependencies relationalDependencies) : base(dependencies, relationalDependencies) @@ -68,7 +67,7 @@ public override void ProcessPropertyAnnotationChanged( /// The property. /// The store value generation strategy to set for the given property. public static new ValueGenerated? GetValueGenerated([NotNull] IProperty property) - => RelationalValueGeneratorConvention.GetValueGenerated(property) + => RelationalValueGenerationConvention.GetValueGenerated(property) ?? ((property as IConventionProperty)?.GetSqlServerValueGenerationStrategyConfigurationSource() != null && property.GetSqlServerValueGenerationStrategy() != null ? ValueGenerated.OnAdd diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationStrategyConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationStrategyConvention.cs index d8c857c661d..277e0762b11 100644 --- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationStrategyConvention.cs +++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerValueGenerationStrategyConvention.cs @@ -9,20 +9,19 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures the default model as + /// . /// public class SqlServerValueGenerationStrategyConvention : IModelInitializedConvention, IModelFinalizedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// - public SqlServerValueGenerationStrategyConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) + /// Parameter object containing dependencies for this convention. + /// Parameter object containing relational dependencies for this convention. + public SqlServerValueGenerationStrategyConvention( + [NotNull] ProviderConventionSetBuilderDependencies dependencies, + [NotNull] RelationalConventionSetBuilderDependencies relationalDependencies) { Dependencies = dependencies; } diff --git a/src/EFCore/DbContext.cs b/src/EFCore/DbContext.cs index 94c34d5fe97..a91a9324d89 100644 --- a/src/EFCore/DbContext.cs +++ b/src/EFCore/DbContext.cs @@ -389,13 +389,15 @@ protected internal virtual void OnModelCreating(ModelBuilder modelBuilder) } /// - /// Saves all changes made in this context to the database. + /// + /// Saves all changes made in this context to the database. + /// + /// + /// This method will automatically call to discover any + /// changes to entity instances before saving to the underlying database. This can be disabled via + /// . + /// /// - /// - /// This method will automatically call to discover any - /// changes to entity instances before saving to the underlying database. This can be disabled via - /// . - /// /// /// The number of state entries written to the database. /// @@ -410,17 +412,19 @@ protected internal virtual void OnModelCreating(ModelBuilder modelBuilder) public virtual int SaveChanges() => SaveChanges(acceptAllChangesOnSuccess: true); /// - /// Saves all changes made in this context to the database. + /// + /// Saves all changes made in this context to the database. + /// + /// + /// This method will automatically call to discover any + /// changes to entity instances before saving to the underlying database. This can be disabled via + /// . + /// /// /// /// Indicates whether is called after the changes have /// been sent successfully to the database. /// - /// - /// This method will automatically call to discover any - /// changes to entity instances before saving to the underlying database. This can be disabled via - /// . - /// /// /// The number of state entries written to the database. /// @@ -479,9 +483,9 @@ private void TryDetectChanges(EntityEntry entry) } /// - /// Asynchronously saves all changes made in this context to the database. - /// - /// + /// + /// Saves all changes made in this context to the database. + /// /// /// This method will automatically call to discover any /// changes to entity instances before saving to the underlying database. This can be disabled via @@ -491,8 +495,8 @@ private void TryDetectChanges(EntityEntry entry) /// Multiple active operations on the same context instance are not supported. Use 'await' to ensure /// that any asynchronous operations have completed before calling another method on this context. /// - /// - /// A to observe while waiting for the task to complete. + /// + /// A to observe while waiting for the task to complete. /// /// A task that represents the asynchronous save operation. The task result contains the /// number of state entries written to the database. @@ -509,13 +513,9 @@ public virtual Task SaveChangesAsync(CancellationToken cancellationToken = => SaveChangesAsync(acceptAllChangesOnSuccess: true, cancellationToken: cancellationToken); /// - /// Asynchronously saves all changes made in this context to the database. - /// - /// - /// Indicates whether is called after the changes have - /// been sent successfully to the database. - /// - /// + /// + /// Saves all changes made in this context to the database. + /// /// /// This method will automatically call to discover any /// changes to entity instances before saving to the underlying database. This can be disabled via @@ -525,8 +525,12 @@ public virtual Task SaveChangesAsync(CancellationToken cancellationToken = /// Multiple active operations on the same context instance are not supported. Use 'await' to ensure /// that any asynchronous operations have completed before calling another method on this context. /// - /// - /// A to observe while waiting for the task to complete. + /// + /// + /// Indicates whether is called after the changes have + /// been sent successfully to the database. + /// + /// A to observe while waiting for the task to complete. /// /// A task that represents the asynchronous save operation. The task result contains the /// number of state entries written to the database. diff --git a/src/EFCore/Metadata/Conventions/BackingFieldConvention.cs b/src/EFCore/Metadata/Conventions/BackingFieldConvention.cs index 745b25eb883..ff4ad35b810 100644 --- a/src/EFCore/Metadata/Conventions/BackingFieldConvention.cs +++ b/src/EFCore/Metadata/Conventions/BackingFieldConvention.cs @@ -15,19 +15,25 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + /// A convention that finds backing fields for properties based on their names: + /// * <[property name]>k__BackingField + /// * _[camel-cased property name] + /// * _[property name] + /// * m_[camel-cased property name] + /// * m_[property name] + /// + /// + /// The field type must be of a type that's assignable to or from the property type. + /// If more than one matching field is found an exception is thrown. + /// /// public class BackingFieldConvention : IPropertyAddedConvention, INavigationAddedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public BackingFieldConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; diff --git a/src/EFCore/Metadata/Conventions/BaseTypeDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/BaseTypeDiscoveryConvention.cs index d29ceffb83c..bf8d5b5502b 100644 --- a/src/EFCore/Metadata/Conventions/BaseTypeDiscoveryConvention.cs +++ b/src/EFCore/Metadata/Conventions/BaseTypeDiscoveryConvention.cs @@ -9,19 +9,15 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that finds a base entity type that's already part of the model based on the associated + /// CLR type hierarchy. /// public class BaseTypeDiscoveryConvention : InheritanceDiscoveryConventionBase, IEntityTypeAddedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public BaseTypeDiscoveryConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) : base(dependencies) { diff --git a/src/EFCore/Metadata/Conventions/CascadeDeleteConvention.cs b/src/EFCore/Metadata/Conventions/CascadeDeleteConvention.cs index 499c493639c..2ee432de068 100644 --- a/src/EFCore/Metadata/Conventions/CascadeDeleteConvention.cs +++ b/src/EFCore/Metadata/Conventions/CascadeDeleteConvention.cs @@ -8,19 +8,15 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that sets the delete behavior to for required foreign keys + /// and for optional ones. /// public class CascadeDeleteConvention : IForeignKeyAddedConvention, IForeignKeyRequirednessChangedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public CascadeDeleteConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; @@ -39,7 +35,7 @@ public CascadeDeleteConvention([NotNull] ProviderConventionSetBuilderDependencie public virtual void ProcessForeignKeyAdded( IConventionRelationshipBuilder relationshipBuilder, IConventionContext context) { - var newRelationshipBuilder = relationshipBuilder.OnDelete(TargetDeleteBehavior(relationshipBuilder.Metadata)); + var newRelationshipBuilder = relationshipBuilder.OnDelete(GetTargetDeleteBehavior(relationshipBuilder.Metadata)); if (newRelationshipBuilder != null) { context.StopProcessingIfChanged(newRelationshipBuilder); @@ -58,12 +54,10 @@ public virtual void ProcessForeignKeyRequirednessChanged( } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Returns the delete behavior to set for the given foreign key. /// - protected virtual DeleteBehavior TargetDeleteBehavior([NotNull] IConventionForeignKey foreignKey) + /// The foreign key. + protected virtual DeleteBehavior GetTargetDeleteBehavior([NotNull] IConventionForeignKey foreignKey) => foreignKey.IsRequired ? DeleteBehavior.Cascade : DeleteBehavior.ClientSetNull; } } diff --git a/src/EFCore/Metadata/Conventions/ChangeTrackingStrategyConvention.cs b/src/EFCore/Metadata/Conventions/ChangeTrackingStrategyConvention.cs index 4e0f6ee01f2..560150378b3 100644 --- a/src/EFCore/Metadata/Conventions/ChangeTrackingStrategyConvention.cs +++ b/src/EFCore/Metadata/Conventions/ChangeTrackingStrategyConvention.cs @@ -9,19 +9,15 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that sets a flag on the model to always skip detecting changes if no entity type is using the + /// strategy. /// public class ChangeTrackingStrategyConvention : IModelFinalizedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public ChangeTrackingStrategyConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; diff --git a/src/EFCore/Metadata/Conventions/ConcurrencyCheckAttributeConvention.cs b/src/EFCore/Metadata/Conventions/ConcurrencyCheckAttributeConvention.cs index cb2d8594097..8d5734a694a 100644 --- a/src/EFCore/Metadata/Conventions/ConcurrencyCheckAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/ConcurrencyCheckAttributeConvention.cs @@ -6,44 +6,36 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; -using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures a property as a concurrency token if it has the . /// - public class ConcurrencyCheckAttributeConvention : PropertyAttributeConvention + public class ConcurrencyCheckAttributeConvention : PropertyAttributeConventionBase { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public ConcurrencyCheckAttributeConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) : base(dependencies) { } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called after a property is added to the entity type with an attribute on the associated CLR property or field. /// + /// The builder for the property. + /// The attribute. + /// The member that has the attribute. + /// Additional information associated with convention execution. protected override void ProcessPropertyAdded( IConventionPropertyBuilder propertyBuilder, ConcurrencyCheckAttribute attribute, MemberInfo clrMember, IConventionContext context) { - Check.NotNull(propertyBuilder, nameof(propertyBuilder)); - Check.NotNull(attribute, nameof(attribute)); - propertyBuilder.IsConcurrencyToken(true, fromDataAnnotation: true); } } diff --git a/src/EFCore/Metadata/Conventions/ConstructorBindingConvention.cs b/src/EFCore/Metadata/Conventions/ConstructorBindingConvention.cs index 565ffb7f9d6..03f8a436dca 100644 --- a/src/EFCore/Metadata/Conventions/ConstructorBindingConvention.cs +++ b/src/EFCore/Metadata/Conventions/ConstructorBindingConvention.cs @@ -15,19 +15,20 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that binds entity type constructor parameters to existing properties and service properties based on their names: + /// * [parameter name] + /// * [pascal-cased parameter name] + /// * _[parameter name] + /// * _[pascal-cased parameter name] + /// * m_[parameter name] + /// * m_[pascal-cased parameter name] /// public class ConstructorBindingConvention : IModelFinalizedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public ConstructorBindingConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; @@ -39,11 +40,10 @@ public ConstructorBindingConvention([NotNull] ProviderConventionSetBuilderDepend protected virtual ProviderConventionSetBuilderDependencies Dependencies { get; } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called after a model is finalized. /// + /// The builder for the model. + /// Additional information associated with convention execution. public virtual void ProcessModelFinalized(IConventionModelBuilder modelBuilder, IConventionContext context) { foreach (var entityType in modelBuilder.Metadata.GetEntityTypes()) diff --git a/src/EFCore/Metadata/Conventions/DatabaseGeneratedAttributeConvention.cs b/src/EFCore/Metadata/Conventions/DatabaseGeneratedAttributeConvention.cs index b2daae26131..f1b5c082c5a 100644 --- a/src/EFCore/Metadata/Conventions/DatabaseGeneratedAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/DatabaseGeneratedAttributeConvention.cs @@ -6,44 +6,39 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; -using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that that configures a property as if + /// is specified, if + /// is specified or if + /// is specified using a . /// - public class DatabaseGeneratedAttributeConvention : PropertyAttributeConvention + public class DatabaseGeneratedAttributeConvention : PropertyAttributeConventionBase { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public DatabaseGeneratedAttributeConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) : base(dependencies) { } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called after a property is added to the entity type with an attribute on the associated CLR property or field. /// + /// The builder for the property. + /// The attribute. + /// The member that has the attribute. + /// Additional information associated with convention execution. protected override void ProcessPropertyAdded( IConventionPropertyBuilder propertyBuilder, DatabaseGeneratedAttribute attribute, MemberInfo clrMember, IConventionContext context) { - Check.NotNull(propertyBuilder, nameof(propertyBuilder)); - Check.NotNull(attribute, nameof(attribute)); - var valueGenerated = attribute.DatabaseGeneratedOption == DatabaseGeneratedOption.Identity ? ValueGenerated.OnAdd diff --git a/src/EFCore/Metadata/Conventions/DerivedTypeDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/DerivedTypeDiscoveryConvention.cs index 78a49ee6636..02d7dfb3e78 100644 --- a/src/EFCore/Metadata/Conventions/DerivedTypeDiscoveryConvention.cs +++ b/src/EFCore/Metadata/Conventions/DerivedTypeDiscoveryConvention.cs @@ -11,19 +11,15 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that finds derived entity types that are already part of the model based on the associated + /// CLR type hierarchy. /// public class DerivedTypeDiscoveryConvention : InheritanceDiscoveryConventionBase, IEntityTypeAddedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public DerivedTypeDiscoveryConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) : base(dependencies) { diff --git a/src/EFCore/Metadata/Conventions/DiscriminatorConvention.cs b/src/EFCore/Metadata/Conventions/DiscriminatorConvention.cs index d8051b6ecfa..4e8bb62a9ca 100644 --- a/src/EFCore/Metadata/Conventions/DiscriminatorConvention.cs +++ b/src/EFCore/Metadata/Conventions/DiscriminatorConvention.cs @@ -10,19 +10,14 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures the discriminator value for entity types in a hierarchy as the entity type name. /// public class DiscriminatorConvention : IEntityTypeBaseTypeChangedConvention, IEntityTypeRemovedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public DiscriminatorConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; @@ -112,17 +107,16 @@ public virtual void ProcessEntityTypeRemoved( } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Configures the discriminator values for the given entity types. /// + /// The entity types to configure. + /// The discriminator builder. protected virtual void SetDefaultDiscriminatorValues( - [NotNull] IEnumerable entityTypes, [NotNull] IConventionDiscriminatorBuilder discriminator) + [NotNull] IEnumerable entityTypes, [NotNull] IConventionDiscriminatorBuilder discriminatorBuilder) { foreach (var entityType in entityTypes) { - discriminator.HasValue(entityType, entityType.ShortName()); + discriminatorBuilder.HasValue(entityType, entityType.ShortName()); } } } diff --git a/src/EFCore/Metadata/Conventions/EntityTypeAttributeConvention.cs b/src/EFCore/Metadata/Conventions/EntityTypeAttributeConventionBase.cs similarity index 61% rename from src/EFCore/Metadata/Conventions/EntityTypeAttributeConvention.cs rename to src/EFCore/Metadata/Conventions/EntityTypeAttributeConventionBase.cs index 2899054a581..56f5a2ee893 100644 --- a/src/EFCore/Metadata/Conventions/EntityTypeAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/EntityTypeAttributeConventionBase.cs @@ -12,21 +12,17 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A base type for conventions that perform configuration based on an attribute specified on an entity type. /// - public abstract class EntityTypeAttributeConvention : IEntityTypeAddedConvention + /// The attribute type to look for. + public abstract class EntityTypeAttributeConventionBase : IEntityTypeAddedConvention where TAttribute : Attribute { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// - protected EntityTypeAttributeConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) + /// Parameter object containing dependencies for this convention. + protected EntityTypeAttributeConventionBase([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; } @@ -67,11 +63,11 @@ public virtual void ProcessEntityTypeAdded( } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called after an entity type is added to the model if it has an attribute. /// + /// The builder for the entity type. + /// The attribute. + /// Additional information associated with convention execution. protected abstract void ProcessEntityTypeAdded( [NotNull] IConventionEntityTypeBuilder entityTypeBuilder, [NotNull] TAttribute attribute, diff --git a/src/EFCore/Metadata/Conventions/ForeignKeyAttributeConvention.cs b/src/EFCore/Metadata/Conventions/ForeignKeyAttributeConvention.cs index bec06cb841c..f38ce0436af 100644 --- a/src/EFCore/Metadata/Conventions/ForeignKeyAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/ForeignKeyAttributeConvention.cs @@ -16,19 +16,20 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + /// A convention that configures the foreign key properties associated with a navigation property + /// based on the specified on the properties or the navigation properties. + /// + /// + /// For one-to-one relationships the attribute has to be specified on the navigation property pointing to the principal. + /// /// public class ForeignKeyAttributeConvention : IForeignKeyAddedConvention, IModelFinalizedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public ForeignKeyAttributeConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; diff --git a/src/EFCore/Metadata/Conventions/ForeignKeyIndexConvention.cs b/src/EFCore/Metadata/Conventions/ForeignKeyIndexConvention.cs index 41eaec72bac..4c99c8e159d 100644 --- a/src/EFCore/Metadata/Conventions/ForeignKeyIndexConvention.cs +++ b/src/EFCore/Metadata/Conventions/ForeignKeyIndexConvention.cs @@ -13,10 +13,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that creates indexes on foreign key properties unless they are already covered by existing indexes or keys. /// public class ForeignKeyIndexConvention : IForeignKeyAddedConvention, @@ -32,11 +29,9 @@ public class ForeignKeyIndexConvention : IModelFinalizedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public ForeignKeyIndexConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; @@ -146,7 +141,7 @@ public virtual void ProcessKeyRemoved( { foreach (var otherForeignKey in key.DeclaringEntityType.GetDerivedTypesInclusive() .SelectMany(t => t.GetDeclaredForeignKeys()) - .Where(fk => AreIndexedBy(fk.Properties, fk.IsUnique, key.Properties, coveringIndexUniqueness: true))) + .Where(fk => AreIndexedBy(fk.Properties, fk.IsUnique, key.Properties, coveringIndexUnique: true))) { CreateIndex(otherForeignKey.Properties, otherForeignKey.IsUnique, otherForeignKey.DeclaringEntityType.Builder); } @@ -183,7 +178,7 @@ public virtual void ProcessEntityTypeBaseTypeChanged( else if (newBaseType != null) { var coveringKey = baseKeys.FirstOrDefault( - k => AreIndexedBy(foreignKey.Properties, foreignKey.IsUnique, k.Properties, coveringIndexUniqueness: true)); + k => AreIndexedBy(foreignKey.Properties, foreignKey.IsUnique, k.Properties, coveringIndexUnique: true)); if (coveringKey != null) { RemoveIndex(index); @@ -258,7 +253,7 @@ public virtual void ProcessForeignKeyUniquenessChanged( if (!foreignKey.IsUnique) { var coveringKey = foreignKey.DeclaringEntityType.GetKeys() - .FirstOrDefault(k => AreIndexedBy(foreignKey.Properties, false, k.Properties, coveringIndexUniqueness: true)); + .FirstOrDefault(k => AreIndexedBy(foreignKey.Properties, false, k.Properties, coveringIndexUnique: true)); if (coveringKey != null) { RemoveIndex(index); @@ -291,7 +286,7 @@ public virtual void ProcessIndexUniquenessChanged( { foreach (var otherIndex in index.DeclaringEntityType.GetDerivedTypesInclusive() .SelectMany(t => t.GetDeclaredIndexes()) - .Where(i => i != index && AreIndexedBy(i.Properties, i.IsUnique, index.Properties, coveringIndexUniqueness: true)) + .Where(i => i != index && AreIndexedBy(i.Properties, i.IsUnique, index.Properties, coveringIndexUnique: true)) .ToList()) { RemoveIndex(otherIndex); @@ -301,7 +296,7 @@ public virtual void ProcessIndexUniquenessChanged( { foreach (var foreignKey in index.DeclaringEntityType.GetDerivedTypesInclusive() .SelectMany(t => t.GetDeclaredForeignKeys()) - .Where(fk => fk.IsUnique && AreIndexedBy(fk.Properties, fk.IsUnique, index.Properties, coveringIndexUniqueness: true))) + .Where(fk => fk.IsUnique && AreIndexedBy(fk.Properties, fk.IsUnique, index.Properties, coveringIndexUnique: true))) { CreateIndex(foreignKey.Properties, foreignKey.IsUnique, foreignKey.DeclaringEntityType.Builder); } @@ -319,7 +314,7 @@ protected virtual IConventionIndex CreateIndex( { foreach (var key in entityTypeBuilder.Metadata.GetKeys()) { - if (AreIndexedBy(properties, unique, key.Properties, coveringIndexUniqueness: true)) + if (AreIndexedBy(properties, unique, key.Properties, coveringIndexUnique: true)) { return null; } @@ -343,18 +338,20 @@ protected virtual IConventionIndex CreateIndex( } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Returns a value indicating whether the given properties are already covered by an existing index. /// + /// The properties to check. + /// Whether the index to create should be unique. + /// The properties of an existing index. + /// Whether the existing index is unique. + /// true if the existing index covers the given properties. protected virtual bool AreIndexedBy( [NotNull] IReadOnlyList properties, bool unique, [NotNull] IReadOnlyList coveringIndexProperties, - bool coveringIndexUniqueness) + bool coveringIndexUnique) => (!unique && coveringIndexProperties.Select(p => p.Name).StartsWith(properties.Select(p => p.Name))) - || (unique && coveringIndexUniqueness && coveringIndexProperties.SequenceEqual(properties)); + || (unique && coveringIndexUnique && coveringIndexProperties.SequenceEqual(properties)); private static void RemoveIndex(IConventionIndex index) => index.DeclaringEntityType.Builder.HasNoIndex(index); @@ -380,7 +377,7 @@ public virtual void ProcessModelFinalized(IConventionModelBuilder modelBuilder, foreach (var key in entityType.GetKeys()) { if (AreIndexedBy( - declaredForeignKey.Properties, declaredForeignKey.IsUnique, key.Properties, coveringIndexUniqueness: true)) + declaredForeignKey.Properties, declaredForeignKey.IsUnique, key.Properties, coveringIndexUnique: true)) { if (declaredForeignKey.Properties.Count != key.Properties.Count) { diff --git a/src/EFCore/Metadata/Conventions/ForeignKeyPropertyDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/ForeignKeyPropertyDiscoveryConvention.cs index 5ec3bbf6c8a..be00dea8e21 100644 --- a/src/EFCore/Metadata/Conventions/ForeignKeyPropertyDiscoveryConvention.cs +++ b/src/EFCore/Metadata/Conventions/ForeignKeyPropertyDiscoveryConvention.cs @@ -14,10 +14,24 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + /// A convention that finds foreign key properties for relationships based on their names, ignoring case: + /// * [navigation property name][primary key property name] + /// * [navigation property name]Id + /// * [principal entity name][primary key property name] + /// * [principal entity name]Id + /// + /// + /// If no matching properties were found, the relationship is one-to-one, doesn't represent an ownership, + /// the dependent side is not ambiguous and not derived then the primary key properties are used. + /// + /// + /// If a match was found, but the property types are not compatible with the principal key types no further matches are searched for. + /// + /// + /// If the relationship uses shadow properties created by convention they are recreated to remove suffixes + /// used to make the names unique. + /// /// public class ForeignKeyPropertyDiscoveryConvention : IForeignKeyAddedConvention, @@ -36,11 +50,9 @@ public class ForeignKeyPropertyDiscoveryConvention : IModelFinalizedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public ForeignKeyPropertyDiscoveryConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; @@ -237,7 +249,7 @@ private IConventionRelationshipBuilder DiscoverProperties( if (foreignKeyProperties == null) { - return ReuniquifyTemporaryProperties(foreignKey, force: false); + return ((ForeignKey)foreignKey).Builder.ReuniquifyTemporaryProperties(false); } var conflictingFKCount = foreignKey.DeclaringEntityType.FindForeignKeys(foreignKeyProperties) @@ -248,13 +260,13 @@ private IConventionRelationshipBuilder DiscoverProperties( if (foreignKey.Properties.SequenceEqual(foreignKeyProperties)) { return conflictingFKCount > 1 - ? ReuniquifyTemporaryProperties(foreignKey, force: true) + ? ((ForeignKey)foreignKey).Builder.ReuniquifyTemporaryProperties(true) : relationshipBuilder; } if (conflictingFKCount > 0) { - return ReuniquifyTemporaryProperties(foreignKey, force: false); + return ((ForeignKey)foreignKey).Builder.ReuniquifyTemporaryProperties(false); } var newRelationshipBuilder = relationshipBuilder.HasForeignKey(foreignKeyProperties); @@ -266,9 +278,6 @@ private IConventionRelationshipBuilder DiscoverProperties( return relationshipBuilder.Metadata.Builder == null ? null : relationshipBuilder; } - private IConventionRelationshipBuilder ReuniquifyTemporaryProperties(IConventionForeignKey foreignKey, bool force) - => ((ForeignKey)foreignKey).Builder.ReuniquifyTemporaryProperties(force); - private IReadOnlyList FindCandidateForeignKeyProperties( IConventionForeignKey foreignKey, bool onDependent, bool matchPk = false) { diff --git a/src/EFCore/Metadata/Conventions/IModelFinalizedConvention.cs b/src/EFCore/Metadata/Conventions/IModelFinalizedConvention.cs index 8666c89c245..baf7f592f5f 100644 --- a/src/EFCore/Metadata/Conventions/IModelFinalizedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IModelFinalizedConvention.cs @@ -9,7 +9,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when a model is finalized. /// - public interface IModelFinalizedConvention + public interface IModelFinalizedConvention : IConvention { /// /// Called after a model is finalized. diff --git a/src/EFCore/Metadata/Conventions/IModelInitializedConvention.cs b/src/EFCore/Metadata/Conventions/IModelInitializedConvention.cs index 46401f68bea..2bec8b0c758 100644 --- a/src/EFCore/Metadata/Conventions/IModelInitializedConvention.cs +++ b/src/EFCore/Metadata/Conventions/IModelInitializedConvention.cs @@ -9,7 +9,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions /// /// Represents an operation that should be performed when a model is initialized. /// - public interface IModelInitializedConvention + public interface IModelInitializedConvention : IConvention { /// /// Called after a model is initialized. diff --git a/src/EFCore/Metadata/Conventions/Infrastructure/ProviderConventionSetBuilder.cs b/src/EFCore/Metadata/Conventions/Infrastructure/ProviderConventionSetBuilder.cs index 2a8cb9ae6e3..9da10e28d7a 100644 --- a/src/EFCore/Metadata/Conventions/Infrastructure/ProviderConventionSetBuilder.cs +++ b/src/EFCore/Metadata/Conventions/Infrastructure/ProviderConventionSetBuilder.cs @@ -80,7 +80,7 @@ public virtual ConventionSet CreateConventionSet() conventionSet.EntityTypeRemovedConventions.Add(discriminatorConvention); var foreignKeyIndexConvention = new ForeignKeyIndexConvention(Dependencies); - var valueGeneratorConvention = new ValueGeneratorConvention(Dependencies); + var valueGeneratorConvention = new ValueGenerationConvention(Dependencies); conventionSet.EntityTypeBaseTypeChangedConventions.Add(propertyDiscoveryConvention); conventionSet.EntityTypeBaseTypeChangedConventions.Add(servicePropertyDiscoveryConvention); diff --git a/src/EFCore/Metadata/Conventions/InheritanceDiscoveryConventionBase.cs b/src/EFCore/Metadata/Conventions/InheritanceDiscoveryConventionBase.cs index 2d633f7b2e7..019e9b32c3a 100644 --- a/src/EFCore/Metadata/Conventions/InheritanceDiscoveryConventionBase.cs +++ b/src/EFCore/Metadata/Conventions/InheritanceDiscoveryConventionBase.cs @@ -9,19 +9,14 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Base type for inheritance discovery conventions /// public abstract class InheritanceDiscoveryConventionBase { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. protected InheritanceDiscoveryConventionBase([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; @@ -33,11 +28,10 @@ protected InheritanceDiscoveryConventionBase([NotNull] ProviderConventionSetBuil protected virtual ProviderConventionSetBuilderDependencies Dependencies { get; } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Finds an entity type in the model that's associated with a CLR type that the given entity type's + /// associated CLR type is derived from and is the closest one in the CLR hierarchy. /// + /// The entity type. protected virtual IConventionEntityType FindClosestBaseType([NotNull] IConventionEntityType entityType) { Check.NotNull(entityType, nameof(entityType)); diff --git a/src/EFCore/Metadata/Conventions/InversePropertyAttributeConvention.cs b/src/EFCore/Metadata/Conventions/InversePropertyAttributeConvention.cs index a52fc73f4e2..8aa24886f12 100644 --- a/src/EFCore/Metadata/Conventions/InversePropertyAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/InversePropertyAttributeConvention.cs @@ -17,31 +17,29 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures the inverse navigation property based on the + /// specified on the other navigation property. /// public class InversePropertyAttributeConvention : - NavigationAttributeEntityTypeConvention, IModelFinalizedConvention + NavigationAttributeConventionBase, IModelFinalizedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public InversePropertyAttributeConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) : base(dependencies) { } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called for every navigation property that has an attribute after an entity type is added to the model. /// + /// The builder for the entity type. + /// The navigation member info. + /// The CLR type of the target entity type + /// The attribute. + /// Additional information associated with convention execution. public override void ProcessEntityTypeAdded( IConventionEntityTypeBuilder entityTypeBuilder, MemberInfo navigationMemberInfo, @@ -82,7 +80,7 @@ private IConventionRelationshipBuilder ConfigureInverseNavigation( .FirstOrDefault(p => string.Equals(p.GetSimpleMemberName(), attribute.Property, StringComparison.OrdinalIgnoreCase)); if (inverseNavigationPropertyInfo == null - || !FindCandidateNavigationPropertyType(inverseNavigationPropertyInfo).GetTypeInfo() + || !Dependencies.MemberClassifier.FindCandidateNavigationPropertyType(inverseNavigationPropertyInfo).GetTypeInfo() .IsAssignableFrom(entityType.ClrType.GetTypeInfo())) { throw new InvalidOperationException( @@ -100,7 +98,7 @@ private IConventionRelationshipBuilder ConfigureInverseNavigation( entityType.DisplayName())); } - // Check for InversePropertyAttribute on the inverseNavigation to verify that it matches. + // Check for InversePropertyAttribute on the inverse navigation to verify that it matches. if (Attribute.IsDefined(inverseNavigationPropertyInfo, typeof(InversePropertyAttribute))) { var inverseAttribute = inverseNavigationPropertyInfo.GetCustomAttribute(true); @@ -209,11 +207,14 @@ private IConventionRelationshipBuilder ConfigureInverseNavigation( } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called for every navigation property that has an attribute after an entity type is ignored. /// + /// The builder for the model. + /// The ignored entity type. + /// The navigation member info. + /// The CLR type of the target entity type. + /// The attribute. + /// Additional information associated with convention execution. public override void ProcessEntityTypeIgnored( IConventionModelBuilder modelBuilder, Type type, @@ -239,11 +240,12 @@ public override void ProcessEntityTypeIgnored( } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called after a navigation property that has an attribute is added to an entity type. /// + /// The builder for the relationship. + /// The navigation. + /// The attribute. + /// Additional information associated with convention execution. public override void ProcessNavigationAdded( IConventionRelationshipBuilder relationshipBuilder, IConventionNavigation navigation, @@ -274,11 +276,15 @@ public override void ProcessNavigationAdded( } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called for every navigation property that has an attribute after the base type for an entity type is changed. /// + /// The builder for the entity type. + /// The new base type. + /// The old base type. + /// The navigation member info. + /// The CLR type of the target entity type. + /// The attribute. + /// Additional information associated with convention execution. public override void ProcessEntityTypeBaseTypeChanged( IConventionEntityTypeBuilder entityTypeBuilder, IConventionEntityType newBaseType, @@ -309,11 +315,13 @@ public override void ProcessEntityTypeBaseTypeChanged( } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called after a navigation property that has an attribute is ignored. /// + /// The builder for the entity type. + /// The navigation member info. + /// The CLR type of the target entity type. + /// The attribute. + /// Additional information associated with convention execution. public override void ProcessEntityTypeMemberIgnored( IConventionEntityTypeBuilder entityTypeBuilder, MemberInfo navigationMemberInfo, @@ -374,11 +382,15 @@ public virtual void ProcessModelFinalized(IConventionModelBuilder modelBuilder, } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Returns a value indication whether the given navigation has ambiguous inverse navigations with + /// . /// + /// The entity type. + /// The navigation. + /// Target entity type. + /// + /// true if the given navigation has ambiguous inverse navigations with . + /// public static bool IsAmbiguous( [NotNull] IConventionEntityType entityType, [NotNull] MemberInfo navigation, [NotNull] IConventionEntityType targetEntityType) { diff --git a/src/EFCore/Metadata/Conventions/KeyAttributeConvention.cs b/src/EFCore/Metadata/Conventions/KeyAttributeConvention.cs index 5d7295b57c3..336dc556289 100644 --- a/src/EFCore/Metadata/Conventions/KeyAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/KeyAttributeConvention.cs @@ -11,41 +11,36 @@ using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures the entity type key based on the specified on a property. /// - public class KeyAttributeConvention : PropertyAttributeConvention, IModelFinalizedConvention + public class KeyAttributeConvention : PropertyAttributeConventionBase, IModelFinalizedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public KeyAttributeConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) : base(dependencies) { } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called after a property is added to the entity type with an attribute on the associated CLR property or field. /// + /// The builder for the property. + /// The attribute. + /// The member that has the attribute. + /// Additional information associated with convention execution. protected override void ProcessPropertyAdded( - IConventionPropertyBuilder propertyBuilder, KeyAttribute attribute, MemberInfo clrMember, IConventionContext context) + IConventionPropertyBuilder propertyBuilder, + KeyAttribute attribute, + MemberInfo clrMember, + IConventionContext context) { - Check.NotNull(propertyBuilder, nameof(propertyBuilder)); - Check.NotNull(attribute, nameof(attribute)); - var entityType = propertyBuilder.Metadata.DeclaringEntityType; if (entityType.BaseType != null) { diff --git a/src/EFCore/Metadata/Conventions/KeyDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/KeyDiscoveryConvention.cs index 7c4b7d87130..2a85ecde1ef 100644 --- a/src/EFCore/Metadata/Conventions/KeyDiscoveryConvention.cs +++ b/src/EFCore/Metadata/Conventions/KeyDiscoveryConvention.cs @@ -15,10 +15,19 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + /// A convention that finds primary key property for the entity type based on the names, ignoring case: + /// * Id + /// * [entity name]Id + /// + /// If the entity type is owned through a reference navigation property then the corresponding foreign key + /// properties are used. + /// + /// + /// + /// If the entity type is owned through a collection navigation property then a composite primary key + /// is configured using the foreign key properties with an extra property that matches the naming convention above. + /// /// public class KeyDiscoveryConvention : IEntityTypeAddedConvention, @@ -35,11 +44,9 @@ public class KeyDiscoveryConvention : private const string KeySuffix = "Id"; /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public KeyDiscoveryConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; @@ -78,8 +85,8 @@ private void TryConfigurePrimaryKey(IConventionEntityTypeBuilder entityTypeBuild { var candidateProperties = entityType.GetProperties().Where( p => !p.IsShadowProperty() - || !ConfigurationSource.Convention.Overrides(p.GetConfigurationSource())).ToList(); - keyProperties = (List)DiscoverKeyProperties(entityType, candidateProperties); + || !ConfigurationSource.Convention.Overrides(p.GetConfigurationSource())); + keyProperties = DiscoverKeyProperties(entityType, candidateProperties).ToList(); if (keyProperties.Count > 1) { Dependencies.Logger.MultiplePrimaryKeyCandidates(keyProperties[0], keyProperties[1]); @@ -118,29 +125,30 @@ private void TryConfigurePrimaryKey(IConventionEntityTypeBuilder entityTypeBuild } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Returns the properties that should be used for the primary key. /// - public virtual IEnumerable DiscoverKeyProperties( + /// The entity type. + /// The properties to consider. + /// The properties that should be used for the primary key. + public static IEnumerable DiscoverKeyProperties( [NotNull] IConventionEntityType entityType, - [NotNull] IReadOnlyList candidateProperties) + [NotNull] IEnumerable candidateProperties) { Check.NotNull(entityType, nameof(entityType)); - var keyProperties = candidateProperties.Where(p => string.Equals(p.Name, KeySuffix, StringComparison.OrdinalIgnoreCase)) - .ToList(); - if (keyProperties.Count == 0) + // ReSharper disable PossibleMultipleEnumeration + var keyProperties = candidateProperties.Where(p => string.Equals(p.Name, KeySuffix, StringComparison.OrdinalIgnoreCase)); + if (!keyProperties.Any()) { var entityTypeName = entityType.ShortName(); keyProperties = candidateProperties.Where( p => p.Name.Length == entityTypeName.Length + KeySuffix.Length && p.Name.StartsWith(entityTypeName, StringComparison.OrdinalIgnoreCase) - && p.Name.EndsWith(KeySuffix, StringComparison.OrdinalIgnoreCase)).ToList(); + && p.Name.EndsWith(KeySuffix, StringComparison.OrdinalIgnoreCase)); } return keyProperties; + // ReSharper restore PossibleMultipleEnumeration } /// diff --git a/src/EFCore/Metadata/Conventions/MaxLengthAttributeConvention.cs b/src/EFCore/Metadata/Conventions/MaxLengthAttributeConvention.cs index 6fb7ddbbd1c..68216485898 100644 --- a/src/EFCore/Metadata/Conventions/MaxLengthAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/MaxLengthAttributeConvention.cs @@ -6,41 +6,36 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; -using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures the maximum length based on the applied on the property. /// - public class MaxLengthAttributeConvention : PropertyAttributeConvention + public class MaxLengthAttributeConvention : PropertyAttributeConventionBase { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public MaxLengthAttributeConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) : base(dependencies) { } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called after a property is added to the entity type with an attribute on the associated CLR property or field. /// + /// The builder for the property. + /// The attribute. + /// The member that has the attribute. + /// Additional information associated with convention execution. protected override void ProcessPropertyAdded( - IConventionPropertyBuilder propertyBuilder, MaxLengthAttribute attribute, MemberInfo clrMember, IConventionContext context) + IConventionPropertyBuilder propertyBuilder, + MaxLengthAttribute attribute, + MemberInfo clrMember, + IConventionContext context) { - Check.NotNull(propertyBuilder, nameof(propertyBuilder)); - Check.NotNull(attribute, nameof(attribute)); - if (attribute.Length > 0) { propertyBuilder.HasMaxLength(attribute.Length, fromDataAnnotation: true); diff --git a/src/EFCore/Metadata/Conventions/ModelCleanupConvention.cs b/src/EFCore/Metadata/Conventions/ModelCleanupConvention.cs index 55ec8c852a8..064f1950579 100644 --- a/src/EFCore/Metadata/Conventions/ModelCleanupConvention.cs +++ b/src/EFCore/Metadata/Conventions/ModelCleanupConvention.cs @@ -11,19 +11,14 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that removes any state that is only used during model building. /// public class ModelCleanupConvention : IModelFinalizedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public ModelCleanupConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; diff --git a/src/EFCore/Metadata/Conventions/NavigationAttributeEntityTypeConvention.cs b/src/EFCore/Metadata/Conventions/NavigationAttributeConventionBase.cs similarity index 60% rename from src/EFCore/Metadata/Conventions/NavigationAttributeEntityTypeConvention.cs rename to src/EFCore/Metadata/Conventions/NavigationAttributeConventionBase.cs index d1ed0c17738..1dbb21923f2 100644 --- a/src/EFCore/Metadata/Conventions/NavigationAttributeEntityTypeConvention.cs +++ b/src/EFCore/Metadata/Conventions/NavigationAttributeConventionBase.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Linq; using System.Reflection; using JetBrains.Annotations; @@ -10,34 +11,36 @@ using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal; using Microsoft.EntityFrameworkCore.Metadata.Internal; +using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A base type for conventions that perform configuration based on an attribute applied to a navigation. /// - public abstract class NavigationAttributeEntityTypeConvention : - NavigationAttributeNavigationConvention, + /// The attribute type to look for. + public abstract class NavigationAttributeConventionBase : IEntityTypeAddedConvention, IEntityTypeIgnoredConvention, IEntityTypeBaseTypeChangedConvention, + INavigationAddedConvention, IEntityTypeMemberIgnoredConvention where TAttribute : Attribute { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// - protected NavigationAttributeEntityTypeConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) - : base(dependencies) + /// Parameter object containing dependencies for this convention. + protected NavigationAttributeConventionBase([NotNull] ProviderConventionSetBuilderDependencies dependencies) { + Dependencies = dependencies; } + /// + /// Parameter object containing service dependencies. + /// + protected virtual ProviderConventionSetBuilderDependencies Dependencies { get; } + /// /// Called after an entity type is added to the model. /// @@ -96,6 +99,8 @@ public virtual void ProcessEntityTypeIgnored( continue; } + type.IsDefined(typeof(TAttribute)); + navigationPropertyInfo.IsDefined(typeof(TAttribute)); var attributes = navigationPropertyInfo.GetCustomAttributes(true); foreach (var attribute in attributes) { @@ -148,6 +153,30 @@ public virtual void ProcessEntityTypeBaseTypeChanged( } } } + /// + /// Called after a navigation is added to the entity type. + /// + /// The builder for the foreign key. + /// The navigation. + /// Additional information associated with convention execution. + public virtual void ProcessNavigationAdded( + IConventionRelationshipBuilder relationshipBuilder, + IConventionNavigation navigation, + IConventionContext context) + { + Check.NotNull(relationshipBuilder, nameof(relationshipBuilder)); + Check.NotNull(navigation, nameof(navigation)); + + var attributes = GetAttributes(navigation.DeclaringEntityType, navigation); + foreach (var attribute in attributes) + { + ProcessNavigationAdded(relationshipBuilder, navigation, attribute, context); + if (((IReadableConventionContext)context).ShouldStopProcessing()) + { + break; + } + } + } /// /// Called after an entity type member is ignored. @@ -182,15 +211,6 @@ public virtual void ProcessEntityTypeMemberIgnored( } } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - protected virtual Type FindCandidateNavigationPropertyType([NotNull] PropertyInfo propertyInfo) - => Dependencies.MemberClassifier.FindCandidateNavigationPropertyType(propertyInfo); - private Type FindCandidateNavigationWithAttributePropertyType([NotNull] PropertyInfo propertyInfo) { var targetClrType = Dependencies.MemberClassifier.FindCandidateNavigationPropertyType(propertyInfo); @@ -201,11 +221,39 @@ private Type FindCandidateNavigationWithAttributePropertyType([NotNull] Property } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Returns the attributes applied to the given navigation. + /// + /// The entity type. + /// The navigation. + /// The attribute type to look for. + /// The attributes applied to the given navigation. + protected static IEnumerable GetAttributes( + [NotNull] IConventionEntityType entityType, [NotNull] IConventionNavigation navigation) + where TCustomAttribute : Attribute + { + Check.NotNull(entityType, nameof(entityType)); + Check.NotNull(navigation, nameof(navigation)); + + var memberInfo = navigation.GetIdentifyingMemberInfo(); + if (!entityType.HasClrType() + || memberInfo == null) + { + return Enumerable.Empty(); + } + + return Attribute.IsDefined(memberInfo, typeof(TCustomAttribute), inherit: true) + ? memberInfo.GetCustomAttributes(true) + : Enumerable.Empty(); + } + + /// + /// Called for every navigation property that has an attribute after an entity type is added to the model. /// + /// The builder for the entity type. + /// The navigation member info. + /// The CLR type of the target entity type + /// The attribute. + /// Additional information associated with convention execution. public virtual void ProcessEntityTypeAdded( [NotNull] IConventionEntityTypeBuilder entityTypeBuilder, [NotNull] MemberInfo navigationMemberInfo, @@ -215,11 +263,14 @@ public virtual void ProcessEntityTypeAdded( => throw new NotImplementedException(); /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called for every navigation property that has an attribute after an entity type is ignored. /// + /// The builder for the model. + /// The ignored entity type. + /// The navigation member info. + /// The CLR type of the target entity type. + /// The attribute. + /// Additional information associated with convention execution. public virtual void ProcessEntityTypeIgnored( [NotNull] IConventionModelBuilder modelBuilder, [NotNull] Type type, @@ -230,24 +281,15 @@ public virtual void ProcessEntityTypeIgnored( => throw new NotImplementedException(); /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public override void ProcessNavigationAdded( - IConventionRelationshipBuilder relationshipBuilder, - IConventionNavigation navigation, - TAttribute attribute, - IConventionContext context) - => throw new NotImplementedException(); - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called for every navigation property that has an attribute after the base type for an entity type is changed. /// + /// The builder for the entity type. + /// The new base type. + /// The old base type. + /// The navigation member info. + /// The CLR type of the target entity type. + /// The attribute. + /// Additional information associated with convention execution. public virtual void ProcessEntityTypeBaseTypeChanged( [NotNull] IConventionEntityTypeBuilder entityTypeBuilder, [CanBeNull] IConventionEntityType newBaseType, @@ -259,11 +301,27 @@ public virtual void ProcessEntityTypeBaseTypeChanged( => throw new NotImplementedException(); /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called after a navigation property that has an attribute is added to an entity type. /// + /// The builder for the relationship. + /// The navigation. + /// The attribute. + /// Additional information associated with convention execution. + public virtual void ProcessNavigationAdded( + [NotNull] IConventionRelationshipBuilder relationshipBuilder, + [NotNull] IConventionNavigation navigation, + [NotNull] TAttribute attribute, + [NotNull] IConventionContext context) + => throw new NotImplementedException(); + + /// + /// Called after a navigation property that has an attribute is ignored. + /// + /// The builder for the entity type. + /// The navigation member info. + /// The CLR type of the target entity type. + /// The attribute. + /// Additional information associated with convention execution. public virtual void ProcessEntityTypeMemberIgnored( [NotNull] IConventionEntityTypeBuilder entityTypeBuilder, [NotNull] MemberInfo navigationMemberInfo, diff --git a/src/EFCore/Metadata/Conventions/NavigationAttributeNavigationConvention.cs b/src/EFCore/Metadata/Conventions/NavigationAttributeNavigationConvention.cs deleted file mode 100644 index d6874812b6d..00000000000 --- a/src/EFCore/Metadata/Conventions/NavigationAttributeNavigationConvention.cs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using JetBrains.Annotations; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal; -using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Utilities; - -namespace Microsoft.EntityFrameworkCore.Metadata.Conventions -{ - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public abstract class NavigationAttributeNavigationConvention : INavigationAddedConvention - where TAttribute : Attribute - { - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - protected NavigationAttributeNavigationConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) - { - Dependencies = dependencies; - } - - /// - /// Parameter object containing service dependencies. - /// - protected virtual ProviderConventionSetBuilderDependencies Dependencies { get; } - - /// - /// Called after a navigation is added to the entity type. - /// - /// The builder for the foreign key. - /// The navigation. - /// Additional information associated with convention execution. - public virtual void ProcessNavigationAdded( - IConventionRelationshipBuilder relationshipBuilder, - IConventionNavigation navigation, - IConventionContext context) - { - Check.NotNull(relationshipBuilder, nameof(relationshipBuilder)); - Check.NotNull(navigation, nameof(navigation)); - - var attributes = GetAttributes(navigation.DeclaringEntityType, navigation); - foreach (var attribute in attributes) - { - ProcessNavigationAdded(relationshipBuilder, navigation, attribute, context); - if (((IReadableConventionContext)context).ShouldStopProcessing()) - { - break; - } - } - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public abstract void ProcessNavigationAdded( - [NotNull] IConventionRelationshipBuilder relationshipBuilder, - [NotNull] IConventionNavigation navigation, - [NotNull] TAttribute attribute, - [NotNull] IConventionContext context); - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - protected static IEnumerable GetAttributes( - [NotNull] IConventionEntityType entityType, [NotNull] IConventionNavigation navigation) - where TCustomAttribute : Attribute - { - Check.NotNull(entityType, nameof(entityType)); - Check.NotNull(navigation, nameof(navigation)); - - var memberInfo = navigation.GetIdentifyingMemberInfo(); - if (!entityType.HasClrType() - || memberInfo == null) - { - return Enumerable.Empty(); - } - - return Attribute.IsDefined(memberInfo, typeof(TCustomAttribute), inherit: true) - ? memberInfo.GetCustomAttributes(true) - : Enumerable.Empty(); - } - } -} diff --git a/src/EFCore/Metadata/Conventions/NavigationEagerLoadingConvention.cs b/src/EFCore/Metadata/Conventions/NavigationEagerLoadingConvention.cs index 8d75a109227..941cb425538 100644 --- a/src/EFCore/Metadata/Conventions/NavigationEagerLoadingConvention.cs +++ b/src/EFCore/Metadata/Conventions/NavigationEagerLoadingConvention.cs @@ -8,19 +8,14 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures the navigations to owned entity types as eager loaded. /// public class NavigationEagerLoadingConvention : IForeignKeyOwnershipChangedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public NavigationEagerLoadingConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; diff --git a/src/EFCore/Metadata/Conventions/NonNullableConvention.cs b/src/EFCore/Metadata/Conventions/NonNullableConventionBase.cs similarity index 62% rename from src/EFCore/Metadata/Conventions/NonNullableConvention.cs rename to src/EFCore/Metadata/Conventions/NonNullableConventionBase.cs index 37a235c8bd8..832aca36cc1 100644 --- a/src/EFCore/Metadata/Conventions/NonNullableConvention.cs +++ b/src/EFCore/Metadata/Conventions/NonNullableConventionBase.cs @@ -10,24 +10,20 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A base type for conventions that configure model aspects based on whether the member type + /// is a non-nullable reference type. /// - public abstract class NonNullableConvention + public abstract class NonNullableConventionBase { private const string NullableAttributeFullName = "System.Runtime.CompilerServices.NullableAttribute"; private Type _nullableAttrType; private FieldInfo _nullableFlagsFieldInfo; - + /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// - protected NonNullableConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) + /// Parameter object containing dependencies for this convention. + protected NonNullableConventionBase([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; } @@ -38,11 +34,10 @@ protected NonNullableConvention([NotNull] ProviderConventionSetBuilderDependenci protected virtual ProviderConventionSetBuilderDependencies Dependencies { get; } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Returns a value indicating whether the member type is a non-nullable reference type. /// + /// The member info. + /// true if the member type is a non-nullable reference type. protected virtual bool IsNonNullable([NotNull] MemberInfo memberInfo) { // For C# 8.0 nullable types, the C# currently synthesizes a NullableAttribute that expresses nullability into assemblies diff --git a/src/EFCore/Metadata/Conventions/NonNullableNavigationConvention.cs b/src/EFCore/Metadata/Conventions/NonNullableNavigationConvention.cs index 185ecc9554e..b3c90579715 100644 --- a/src/EFCore/Metadata/Conventions/NonNullableNavigationConvention.cs +++ b/src/EFCore/Metadata/Conventions/NonNullableNavigationConvention.cs @@ -13,19 +13,14 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures the non-nullable navigations to principal entity type as required. /// - public class NonNullableNavigationConvention : NonNullableConvention, INavigationAddedConvention + public class NonNullableNavigationConvention : NonNullableConventionBase, INavigationAddedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public NonNullableNavigationConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) : base(dependencies) { diff --git a/src/EFCore/Metadata/Conventions/NonNullableReferencePropertyConvention.cs b/src/EFCore/Metadata/Conventions/NonNullableReferencePropertyConvention.cs index 74b5148d269..aa364b5d811 100644 --- a/src/EFCore/Metadata/Conventions/NonNullableReferencePropertyConvention.cs +++ b/src/EFCore/Metadata/Conventions/NonNullableReferencePropertyConvention.cs @@ -10,20 +10,15 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures the properties of non-nullable types as required. /// - public class NonNullableReferencePropertyConvention : NonNullableConvention, + public class NonNullableReferencePropertyConvention : NonNullableConventionBase, IPropertyAddedConvention, IPropertyFieldChangedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public NonNullableReferencePropertyConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) : base(dependencies) { diff --git a/src/EFCore/Metadata/Conventions/NotMappedEntityTypeAttributeConvention.cs b/src/EFCore/Metadata/Conventions/NotMappedEntityTypeAttributeConvention.cs index b55e8a68f85..bc7bc8b9dba 100644 --- a/src/EFCore/Metadata/Conventions/NotMappedEntityTypeAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/NotMappedEntityTypeAttributeConvention.cs @@ -5,43 +5,34 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; -using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that ignores entity types that have the . /// - public class NotMappedEntityTypeAttributeConvention : EntityTypeAttributeConvention + public class NotMappedEntityTypeAttributeConvention : EntityTypeAttributeConventionBase { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public NotMappedEntityTypeAttributeConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) : base(dependencies) { } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called after an entity type is added to the model if it has an attribute. /// + /// The builder for the entity type. + /// The attribute. + /// Additional information associated with convention execution. protected override void ProcessEntityTypeAdded( IConventionEntityTypeBuilder entityTypeBuilder, NotMappedAttribute attribute, IConventionContext context) { - Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder)); - Check.NotNull(attribute, nameof(attribute)); - if (entityTypeBuilder.ModelBuilder.Ignore(entityTypeBuilder.Metadata.Name, fromDataAnnotation: true) != null) { context.StopProcessing(); diff --git a/src/EFCore/Metadata/Conventions/NotMappedMemberAttributeConvention.cs b/src/EFCore/Metadata/Conventions/NotMappedMemberAttributeConvention.cs index fc843e6f21f..d64d0cd8dbd 100644 --- a/src/EFCore/Metadata/Conventions/NotMappedMemberAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/NotMappedMemberAttributeConvention.cs @@ -14,19 +14,14 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that ignores members on entity types that have the . /// public class NotMappedMemberAttributeConvention : IEntityTypeAddedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public NotMappedMemberAttributeConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; diff --git a/src/EFCore/Metadata/Conventions/OwnedEntityTypeAttributeConvention.cs b/src/EFCore/Metadata/Conventions/OwnedEntityTypeAttributeConvention.cs index 56e14fc1e6e..92033ac3227 100644 --- a/src/EFCore/Metadata/Conventions/OwnedEntityTypeAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/OwnedEntityTypeAttributeConvention.cs @@ -9,32 +9,28 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures the entity types that have the as owned. /// - public class OwnedEntityTypeAttributeConvention : EntityTypeAttributeConvention + public class OwnedEntityTypeAttributeConvention : EntityTypeAttributeConventionBase { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public OwnedEntityTypeAttributeConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) : base(dependencies) { } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called after an entity type is added to the model if it has an attribute. /// + /// The builder for the entity type. + /// The attribute. + /// Additional information associated with convention execution. protected override void ProcessEntityTypeAdded( - IConventionEntityTypeBuilder entityTypeBuilder, OwnedAttribute attribute, + IConventionEntityTypeBuilder entityTypeBuilder, + OwnedAttribute attribute, IConventionContext context) { if (entityTypeBuilder.Metadata.HasClrType()) diff --git a/src/EFCore/Metadata/Conventions/OwnedTypesConvention.cs b/src/EFCore/Metadata/Conventions/OwnedTypesConvention.cs index f4045340d0b..65a947ecb10 100644 --- a/src/EFCore/Metadata/Conventions/OwnedTypesConvention.cs +++ b/src/EFCore/Metadata/Conventions/OwnedTypesConvention.cs @@ -10,19 +10,15 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures owned entity types with defining navigation as owned entity types + /// without defining navigation if there's only one navigation of this type. /// public class OwnedTypesConvention : IEntityTypeRemovedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public OwnedTypesConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; diff --git a/src/EFCore/Metadata/Conventions/PropertyAttributeConvention.cs b/src/EFCore/Metadata/Conventions/PropertyAttributeConventionBase.cs similarity index 70% rename from src/EFCore/Metadata/Conventions/PropertyAttributeConvention.cs rename to src/EFCore/Metadata/Conventions/PropertyAttributeConventionBase.cs index 67929bcce7d..d27d1488745 100644 --- a/src/EFCore/Metadata/Conventions/PropertyAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/PropertyAttributeConventionBase.cs @@ -13,21 +13,17 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A base type for conventions that perform configuration based on an attribute applied to a property. /// - public abstract class PropertyAttributeConvention : IPropertyAddedConvention, IPropertyFieldChangedConvention + /// The attribute type to look for. + public abstract class PropertyAttributeConventionBase : IPropertyAddedConvention, IPropertyFieldChangedConvention where TAttribute : Attribute { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// - protected PropertyAttributeConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) + /// Parameter object containing dependencies for this convention. + protected PropertyAttributeConventionBase([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; } @@ -97,11 +93,12 @@ private void Process(IConventionPropertyBuilder propertyBuilder, MemberInfo memb } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called after a property is added to the entity type with an attribute on the associated CLR property or field. /// + /// The builder for the property. + /// The attribute. + /// The member that has the attribute. + /// Additional information associated with convention execution. protected abstract void ProcessPropertyAdded( [NotNull] IConventionPropertyBuilder propertyBuilder, [NotNull] TAttribute attribute, diff --git a/src/EFCore/Metadata/Conventions/PropertyDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/PropertyDiscoveryConvention.cs index dc6d333c8ca..0c319f8940e 100644 --- a/src/EFCore/Metadata/Conventions/PropertyDiscoveryConvention.cs +++ b/src/EFCore/Metadata/Conventions/PropertyDiscoveryConvention.cs @@ -6,24 +6,18 @@ using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that adds properties to entity types corresponding to scalar public properties on the CLR type. /// public class PropertyDiscoveryConvention : IEntityTypeAddedConvention, IEntityTypeBaseTypeChangedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public PropertyDiscoveryConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; @@ -82,18 +76,8 @@ private void Process(IConventionEntityTypeBuilder entityTypeBuilder) } } - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - protected virtual bool IsCandidatePrimitiveProperty([NotNull] PropertyInfo propertyInfo) - { - Check.NotNull(propertyInfo, nameof(propertyInfo)); - - return propertyInfo.IsCandidateProperty() - && Dependencies.TypeMappingSource.FindMapping(propertyInfo) != null; - } + private bool IsCandidatePrimitiveProperty([NotNull] PropertyInfo propertyInfo) + => propertyInfo.IsCandidateProperty() + && Dependencies.TypeMappingSource.FindMapping(propertyInfo) != null; } } diff --git a/src/EFCore/Metadata/Conventions/RelationshipDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/RelationshipDiscoveryConvention.cs index 879c7d782bd..9249413d176 100644 --- a/src/EFCore/Metadata/Conventions/RelationshipDiscoveryConvention.cs +++ b/src/EFCore/Metadata/Conventions/RelationshipDiscoveryConvention.cs @@ -16,10 +16,8 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures relationships between entity types based on the navigation properties + /// as long as there is no ambiguity as to which is the corresponding inverse navigation. /// public class RelationshipDiscoveryConvention : IEntityTypeAddedConvention, @@ -30,11 +28,9 @@ public class RelationshipDiscoveryConvention : IForeignKeyOwnershipChangedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public RelationshipDiscoveryConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; @@ -1017,10 +1013,7 @@ private static bool HasAmbiguousNavigationsTo(IConventionEntityType sourceEntity } private static bool HasDeclaredAmbiguousNavigationsTo(IConventionEntityType sourceEntityType, Type targetClrType) - { - var ambiguousNavigations = GetAmbiguousNavigations(sourceEntityType); - return ambiguousNavigations?.ContainsValue(targetClrType) == true; - } + => GetAmbiguousNavigations(sourceEntityType)?.ContainsValue(targetClrType) == true; private static ImmutableSortedDictionary GetAmbiguousNavigations(IConventionEntityType entityType) => entityType.FindAnnotation(CoreAnnotationNames.AmbiguousNavigations)?.Value diff --git a/src/EFCore/Metadata/Conventions/RequiredNavigationAttributeConvention.cs b/src/EFCore/Metadata/Conventions/RequiredNavigationAttributeConvention.cs index 4eaae6babae..53805698cd0 100644 --- a/src/EFCore/Metadata/Conventions/RequiredNavigationAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/RequiredNavigationAttributeConvention.cs @@ -12,30 +12,27 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures the principal side of the relationship as required if the + /// is applied on the navigation property to the principal entity type /// - public class RequiredNavigationAttributeConvention : NavigationAttributeNavigationConvention + public class RequiredNavigationAttributeConvention : NavigationAttributeConventionBase { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public RequiredNavigationAttributeConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) : base(dependencies) { } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called after a navigation property that has an attribute is added to an entity type. /// + /// The builder for the relationship. + /// The navigation. + /// The attribute. + /// Additional information associated with convention execution. public override void ProcessNavigationAdded( IConventionRelationshipBuilder relationshipBuilder, IConventionNavigation navigation, diff --git a/src/EFCore/Metadata/Conventions/RequiredPropertyAttributeConvention.cs b/src/EFCore/Metadata/Conventions/RequiredPropertyAttributeConvention.cs index 0cb7f06480a..aa96ca9f3c6 100644 --- a/src/EFCore/Metadata/Conventions/RequiredPropertyAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/RequiredPropertyAttributeConvention.cs @@ -6,41 +6,36 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; -using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures properties as required if they have the applied. /// - public class RequiredPropertyAttributeConvention : PropertyAttributeConvention + public class RequiredPropertyAttributeConvention : PropertyAttributeConventionBase { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public RequiredPropertyAttributeConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) : base(dependencies) { } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called after a property is added to the entity type with an attribute on the associated CLR property or field. /// + /// The builder for the property. + /// The attribute. + /// The member that has the attribute. + /// Additional information associated with convention execution. protected override void ProcessPropertyAdded( - IConventionPropertyBuilder propertyBuilder, RequiredAttribute attribute, MemberInfo clrMember, IConventionContext context) + IConventionPropertyBuilder propertyBuilder, + RequiredAttribute attribute, + MemberInfo clrMember, + IConventionContext context) { - Check.NotNull(propertyBuilder, nameof(propertyBuilder)); - Check.NotNull(attribute, nameof(attribute)); - propertyBuilder.IsRequired(true, fromDataAnnotation: true); } } diff --git a/src/EFCore/Metadata/Conventions/ServicePropertyDiscoveryConvention.cs b/src/EFCore/Metadata/Conventions/ServicePropertyDiscoveryConvention.cs index ed15a02c18f..99c5574084f 100644 --- a/src/EFCore/Metadata/Conventions/ServicePropertyDiscoveryConvention.cs +++ b/src/EFCore/Metadata/Conventions/ServicePropertyDiscoveryConvention.cs @@ -16,10 +16,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that adds service properties to entity types. /// public class ServicePropertyDiscoveryConvention : IEntityTypeAddedConvention, @@ -28,11 +25,9 @@ public class ServicePropertyDiscoveryConvention : IModelFinalizedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public ServicePropertyDiscoveryConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; @@ -50,9 +45,7 @@ public ServicePropertyDiscoveryConvention([NotNull] ProviderConventionSetBuilder /// Additional information associated with convention execution. public virtual void ProcessEntityTypeAdded( IConventionEntityTypeBuilder entityTypeBuilder, IConventionContext context) - { - Process(entityTypeBuilder); - } + => Process(entityTypeBuilder); /// /// Called after the base type of an entity type changes. @@ -86,8 +79,9 @@ private void Process(IConventionEntityTypeBuilder entityTypeBuilder) foreach (var propertyInfo in candidates) { - if (entityTypeBuilder.IsIgnored(propertyInfo.GetSimpleMemberName()) - || ConventionEntityTypeExtensions.FindProperty(entityType, propertyInfo) != null + var name = propertyInfo.GetSimpleMemberName(); + if (entityTypeBuilder.IsIgnored(name) + || entityType.FindProperty(propertyInfo) != null || entityType.FindNavigation(propertyInfo) != null || !propertyInfo.IsCandidateProperty(publicOnly: false) || (propertyInfo.IsCandidateProperty() @@ -96,7 +90,7 @@ private void Process(IConventionEntityTypeBuilder entityTypeBuilder) continue; } - var factory = Dependencies.ParameterBindingFactories.FindFactory(propertyInfo.PropertyType, propertyInfo.GetSimpleMemberName()); + var factory = Dependencies.ParameterBindingFactories.FindFactory(propertyInfo.PropertyType, name); if (factory == null) { continue; diff --git a/src/EFCore/Metadata/Conventions/StringLengthAttributeConvention.cs b/src/EFCore/Metadata/Conventions/StringLengthAttributeConvention.cs index 8a9fef6e59d..208e8f6726d 100644 --- a/src/EFCore/Metadata/Conventions/StringLengthAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/StringLengthAttributeConvention.cs @@ -6,41 +6,36 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; -using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures the maximum length based on the applied on the property. /// - public class StringLengthAttributeConvention : PropertyAttributeConvention + public class StringLengthAttributeConvention : PropertyAttributeConventionBase { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public StringLengthAttributeConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) : base(dependencies) { } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called after a property is added to the entity type with an attribute on the associated CLR property or field. /// + /// The builder for the property. + /// The attribute. + /// The member that has the attribute. + /// Additional information associated with convention execution. protected override void ProcessPropertyAdded( - IConventionPropertyBuilder propertyBuilder, StringLengthAttribute attribute, MemberInfo clrMember, IConventionContext context) + IConventionPropertyBuilder propertyBuilder, + StringLengthAttribute attribute, + MemberInfo clrMember, + IConventionContext context) { - Check.NotNull(propertyBuilder, nameof(propertyBuilder)); - Check.NotNull(attribute, nameof(attribute)); - if (attribute.MaximumLength > 0) { propertyBuilder.HasMaxLength(attribute.MaximumLength, fromDataAnnotation: true); diff --git a/src/EFCore/Metadata/Conventions/TimestampAttributeConvention.cs b/src/EFCore/Metadata/Conventions/TimestampAttributeConvention.cs index bd90c720f10..507c18520df 100644 --- a/src/EFCore/Metadata/Conventions/TimestampAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/TimestampAttributeConvention.cs @@ -6,42 +6,36 @@ using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure; -using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures the property as a concurrency token if a is applied to it. /// - public class TimestampAttributeConvention : PropertyAttributeConvention + public class TimestampAttributeConvention : PropertyAttributeConventionBase { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public TimestampAttributeConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) : base(dependencies) { } /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Called after a property is added to the entity type with an attribute on the associated CLR property or field. /// + /// The builder for the property. + /// The attribute. + /// The member that has the attribute. + /// Additional information associated with convention execution. protected override void ProcessPropertyAdded( - IConventionPropertyBuilder propertyBuilder, TimestampAttribute attribute, MemberInfo clrMember, IConventionContext context) + IConventionPropertyBuilder propertyBuilder, + TimestampAttribute attribute, + MemberInfo clrMember, + IConventionContext context) { - Check.NotNull(propertyBuilder, nameof(propertyBuilder)); - Check.NotNull(attribute, nameof(attribute)); - Check.NotNull(clrMember, nameof(clrMember)); - propertyBuilder.ValueGenerated(ValueGenerated.OnAddOrUpdate, fromDataAnnotation: true); propertyBuilder.IsConcurrencyToken(true, fromDataAnnotation: true); } diff --git a/src/EFCore/Metadata/Conventions/TypeMappingConvention.cs b/src/EFCore/Metadata/Conventions/TypeMappingConvention.cs index ddbb5e4f01b..c5c4aed91b7 100644 --- a/src/EFCore/Metadata/Conventions/TypeMappingConvention.cs +++ b/src/EFCore/Metadata/Conventions/TypeMappingConvention.cs @@ -10,19 +10,14 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that creates and assigns store type mapping to entity properties. /// public class TypeMappingConvention : IModelFinalizedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public TypeMappingConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; diff --git a/src/EFCore/Metadata/Conventions/ValidatingConvention.cs b/src/EFCore/Metadata/Conventions/ValidatingConvention.cs index 932be1658fb..c2f2e5b7948 100644 --- a/src/EFCore/Metadata/Conventions/ValidatingConvention.cs +++ b/src/EFCore/Metadata/Conventions/ValidatingConvention.cs @@ -8,19 +8,14 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that checks whether the model is valid. /// public class ValidatingConvention : IModelFinalizedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// + /// Parameter object containing dependencies for this convention. public ValidatingConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; diff --git a/src/EFCore/Metadata/Conventions/ValueGeneratorConvention.cs b/src/EFCore/Metadata/Conventions/ValueGenerationConvention.cs similarity index 88% rename from src/EFCore/Metadata/Conventions/ValueGeneratorConvention.cs rename to src/EFCore/Metadata/Conventions/ValueGenerationConvention.cs index 82951fc3eae..08ba83885e4 100644 --- a/src/EFCore/Metadata/Conventions/ValueGeneratorConvention.cs +++ b/src/EFCore/Metadata/Conventions/ValueGenerationConvention.cs @@ -11,12 +11,10 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// A convention that configures store value generation as on properties that are + /// part of the primary key and not part of any foreign keys. /// - public class ValueGeneratorConvention : + public class ValueGenerationConvention : IEntityTypePrimaryKeyChangedConvention, IForeignKeyAddedConvention, IForeignKeyRemovedConvention, @@ -24,12 +22,10 @@ public class ValueGeneratorConvention : IEntityTypeBaseTypeChangedConvention { /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// Creates a new instance of . /// - public ValueGeneratorConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) + /// Parameter object containing dependencies for this convention. + public ValueGenerationConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; } @@ -135,7 +131,7 @@ public virtual void ProcessEntityTypePrimaryKeyChanged( } } - if (newPrimaryKey != null && newPrimaryKey.Builder != null) + if (newPrimaryKey?.Builder != null) { foreach (var property in newPrimaryKey.Properties) { diff --git a/src/EFCore/Metadata/IPropertyParameterBindingFactory.cs b/src/EFCore/Metadata/IPropertyParameterBindingFactory.cs index 543c9217a50..be580b87be6 100644 --- a/src/EFCore/Metadata/IPropertyParameterBindingFactory.cs +++ b/src/EFCore/Metadata/IPropertyParameterBindingFactory.cs @@ -26,7 +26,7 @@ public interface IPropertyParameterBindingFactory /// The entity type on which the is defined. /// The parameter name. /// The parameter type. - /// The parameter binding, or null if none was found. + /// The parameter binding, or null if none was found. ParameterBinding TryBindParameter( [NotNull] IEntityType entityType, [NotNull] Type parameterType, diff --git a/src/EFCore/Metadata/Internal/IMemberClassifier.cs b/src/EFCore/Metadata/Internal/IMemberClassifier.cs index 401b2056601..2e1b9895b50 100644 --- a/src/EFCore/Metadata/Internal/IMemberClassifier.cs +++ b/src/EFCore/Metadata/Internal/IMemberClassifier.cs @@ -29,6 +29,6 @@ public interface IMemberClassifier /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - Type FindCandidateNavigationPropertyType([NotNull] PropertyInfo propertyInfo); + Type FindCandidateNavigationPropertyType([NotNull] MemberInfo memberInfo); } } diff --git a/src/EFCore/Metadata/Internal/MemberClassifier.cs b/src/EFCore/Metadata/Internal/MemberClassifier.cs index b09e67eff54..f0f8a0d4964 100644 --- a/src/EFCore/Metadata/Internal/MemberClassifier.cs +++ b/src/EFCore/Metadata/Internal/MemberClassifier.cs @@ -51,13 +51,14 @@ public MemberClassifier( /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual Type FindCandidateNavigationPropertyType(PropertyInfo propertyInfo) + public virtual Type FindCandidateNavigationPropertyType(MemberInfo memberInfo) { - Check.NotNull(propertyInfo, nameof(propertyInfo)); + Check.NotNull(memberInfo, nameof(memberInfo)); - var targetType = propertyInfo.PropertyType; + var targetType = memberInfo.GetMemberType(); var targetSequenceType = targetType.TryGetSequenceType(); - if (!propertyInfo.IsCandidateProperty(targetSequenceType == null)) + if (!(memberInfo is PropertyInfo propertyInfo) + || !propertyInfo.IsCandidateProperty(targetSequenceType == null)) { return null; } @@ -68,7 +69,7 @@ public virtual Type FindCandidateNavigationPropertyType(PropertyInfo propertyInf return targetType.GetTypeInfo().IsInterface || targetType.GetTypeInfo().IsValueType || targetType == typeof(object) - || _parameterBindingFactories.FindFactory(propertyInfo.PropertyType, propertyInfo.GetSimpleMemberName()) != null + || _parameterBindingFactories.FindFactory(targetType, memberInfo.GetSimpleMemberName()) != null || _typeMappingSource.FindMapping(targetType) != null || targetType.GetTypeInfo().IsArray ? null diff --git a/src/EFCore/Update/Internal/UpdateAdapter.cs b/src/EFCore/Update/Internal/UpdateAdapter.cs index 73bcd745db7..a25fcf0aa1e 100644 --- a/src/EFCore/Update/Internal/UpdateAdapter.cs +++ b/src/EFCore/Update/Internal/UpdateAdapter.cs @@ -62,7 +62,12 @@ public virtual IEnumerable Entries /// directly from your code. This API may change or be removed in future releases. /// public virtual void DetectChanges() - => _changeDetector.DetectChanges(_stateManager); + { + if (_stateManager.Model[ChangeDetector.SkipDetectChangesAnnotation] == null) + { + _changeDetector.DetectChanges(_stateManager); + } + } /// /// This API supports the Entity Framework Core infrastructure and is not intended to be used diff --git a/test/EFCore.Tests/Metadata/Conventions/Internal/ValueGeneratorConventionTest.cs b/test/EFCore.Tests/Metadata/Conventions/Internal/ValueGeneratorConventionTest.cs index 9faff343f0c..bbddc8baad5 100644 --- a/test/EFCore.Tests/Metadata/Conventions/Internal/ValueGeneratorConventionTest.cs +++ b/test/EFCore.Tests/Metadata/Conventions/Internal/ValueGeneratorConventionTest.cs @@ -495,7 +495,7 @@ public void Identity_is_added_when_foreign_key_is_removed_and_key_is_primary_key private static void RunConvention(InternalEntityTypeBuilder entityBuilder) { - new ValueGeneratorConvention(CreateDependencies()) + new ValueGenerationConvention(CreateDependencies()) .ProcessEntityTypePrimaryKeyChanged( entityBuilder, entityBuilder.Metadata.FindPrimaryKey(), null, new ConventionContext(entityBuilder.Metadata.Model.ConventionDispatcher)); @@ -503,7 +503,7 @@ private static void RunConvention(InternalEntityTypeBuilder entityBuilder) private static void RunConvention(InternalRelationshipBuilder foreignKeyBuilder) { - new ValueGeneratorConvention(CreateDependencies()) + new ValueGenerationConvention(CreateDependencies()) .ProcessForeignKeyAdded( foreignKeyBuilder, new ConventionContext( @@ -512,7 +512,7 @@ private static void RunConvention(InternalRelationshipBuilder foreignKeyBuilder) private static void RunConvention(InternalEntityTypeBuilder entityBuilder, ForeignKey foreignKey) { - new ValueGeneratorConvention(CreateDependencies()) + new ValueGenerationConvention(CreateDependencies()) .ProcessForeignKeyRemoved(entityBuilder, foreignKey, new ConventionContext(entityBuilder.Metadata.Model.ConventionDispatcher)); } @@ -529,7 +529,7 @@ private static InternalModelBuilder CreateInternalModelBuilder() conventions.EntityTypeAddedConventions.Add(new KeyDiscoveryConvention(dependencies)); - var keyConvention = new ValueGeneratorConvention(dependencies); + var keyConvention = new ValueGenerationConvention(dependencies); conventions.ForeignKeyAddedConventions.Add(keyConvention); conventions.ForeignKeyRemovedConventions.Add(keyConvention);