Skip to content

Commit

Permalink
Change builder shape based on API review
Browse files Browse the repository at this point in the history
  • Loading branch information
ajcvickers committed Jul 30, 2023
1 parent 59a4d83 commit 1e2a724
Show file tree
Hide file tree
Showing 20 changed files with 2,162 additions and 175 deletions.
59 changes: 59 additions & 0 deletions src/EFCore/Metadata/Builders/ComplexPropertyBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,65 @@ public virtual ComplexTypePropertyBuilder Property(Type propertyType, string pro
Check.NotNull(propertyType, nameof(propertyType)),
Check.NotEmpty(propertyName, nameof(propertyName)), ConfigurationSource.Explicit)!.Metadata);

/// <summary>
/// Returns an object that can be used to configure a property of the complex type.
/// If no property with the given name exists, then a new property will be added.
/// </summary>
/// <remarks>
/// When adding a new property with this overload the property name must match the
/// name of a CLR property or field on the complex type. This overload cannot be used to
/// add a new shadow state property.
/// </remarks>
/// <param name="propertyName">The name of the property to be configured.</param>
/// <returns>An object that can be used to configure the property.</returns>
public virtual ComplexTypePrimitiveCollectionBuilder PrimitiveCollection(string propertyName)
=> new(
TypeBuilder.Property(
Check.NotEmpty(propertyName, nameof(propertyName)),
ConfigurationSource.Explicit)!.HasElementType(ConfigurationSource.Explicit)!.Metadata);

/// <summary>
/// Returns an object that can be used to configure a property of the complex type.
/// If no property with the given name exists, then a new property will be added.
/// </summary>
/// <remarks>
/// When adding a new property, if a property with the same name exists in the entity class
/// then it will be added to the model. If no property exists in the entity class, then
/// a new shadow state property will be added. A shadow state property is one that does not have a
/// corresponding property in the entity class. The current value for the property is stored in
/// the <see cref="ChangeTracker" /> rather than being stored in instances of the entity class.
/// </remarks>
/// <typeparam name="TProperty">The type of the property to be configured.</typeparam>
/// <param name="propertyName">The name of the property to be configured.</param>
/// <returns>An object that can be used to configure the property.</returns>
public virtual ComplexTypePrimitiveCollectionBuilder<TProperty> PrimitiveCollection<TProperty>(string propertyName)
=> new(
TypeBuilder.Property(
typeof(TProperty),
Check.NotEmpty(propertyName, nameof(propertyName)), ConfigurationSource.Explicit)!
.HasElementType(ConfigurationSource.Explicit)!.Metadata);

/// <summary>
/// Returns an object that can be used to configure a property of the complex type.
/// If no property with the given name exists, then a new property will be added.
/// </summary>
/// <remarks>
/// When adding a new property, if a property with the same name exists in the entity class
/// then it will be added to the model. If no property exists in the entity class, then
/// a new shadow state property will be added. A shadow state property is one that does not have a
/// corresponding property in the entity class. The current value for the property is stored in
/// the <see cref="ChangeTracker" /> rather than being stored in instances of the entity class.
/// </remarks>
/// <param name="propertyType">The type of the property to be configured.</param>
/// <param name="propertyName">The name of the property to be configured.</param>
/// <returns>An object that can be used to configure the property.</returns>
public virtual ComplexTypePrimitiveCollectionBuilder PrimitiveCollection(Type propertyType, string propertyName)
=> new(
TypeBuilder.Property(
Check.NotNull(propertyType, nameof(propertyType)),
Check.NotEmpty(propertyName, nameof(propertyName)), ConfigurationSource.Explicit)!
.HasElementType(ConfigurationSource.Explicit)!.Metadata);

/// <summary>
/// Returns an object that can be used to configure a property of the complex type.
/// If no property with the given name exists, then a new property will be added.
Expand Down
512 changes: 512 additions & 0 deletions src/EFCore/Metadata/Builders/ComplexTypePrimitiveCollectionBuilder.cs

Large diffs are not rendered by default.

365 changes: 365 additions & 0 deletions src/EFCore/Metadata/Builders/ComplexTypePrimitiveCollectionBuilder`.cs

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions src/EFCore/Metadata/Builders/ComplexTypePropertyBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,29 @@ public virtual ComplexTypePropertyBuilder HasField(string fieldName)
return this;
}

/// <summary>
/// Configures the type of primitive value stored by the collection.
/// </summary>
/// <returns>A builder to configure the collection element type.</returns>
public virtual ElementTypeBuilder ElementType()
{
Builder.HasElementType(ConfigurationSource.Explicit);

return new ElementTypeBuilder((IMutableElementType)Builder.Metadata.GetElementType()!);
}

/// <summary>
/// Configures this property as a collection containing elements of a primitive type.
/// </summary>
/// <param name="builderAction">An action that performs configuration of the collection element type.</param>
/// <returns>The same builder instance so that multiple configuration calls can be chained.</returns>
public virtual ComplexTypePropertyBuilder ElementType(Action<ElementTypeBuilder> builderAction)
{
builderAction(ElementType());

return this;
}

/// <summary>
/// Sets the <see cref="PropertyAccessMode" /> to use for this property.
/// </summary>
Expand Down
8 changes: 8 additions & 0 deletions src/EFCore/Metadata/Builders/ComplexTypePropertyBuilder`.cs
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,14 @@ public ComplexTypePropertyBuilder(IMutableProperty property)
public new virtual ComplexTypePropertyBuilder<TProperty> HasField(string fieldName)
=> (ComplexTypePropertyBuilder<TProperty>)base.HasField(fieldName);

/// <summary>
/// Configures this property as a collection containing elements of a primitive type.
/// </summary>
/// <param name="builderAction">An action that performs configuration of the collection element type.</param>
/// <returns>The same builder instance so that multiple configuration calls can be chained.</returns>
public new virtual ComplexTypePropertyBuilder<TProperty> ElementType(Action<ElementTypeBuilder> builderAction)
=> (ComplexTypePropertyBuilder<TProperty>)base.ElementType(builderAction);

/// <summary>
/// Sets the <see cref="PropertyAccessMode" /> to use for this property.
/// </summary>
Expand Down
62 changes: 62 additions & 0 deletions src/EFCore/Metadata/Builders/EntityTypeBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,68 @@ public virtual PropertyBuilder Property(Type propertyType, string propertyName)
Check.NotNull(propertyType, nameof(propertyType)),
Check.NotEmpty(propertyName, nameof(propertyName)), ConfigurationSource.Explicit)!.Metadata);

/// <summary>
/// Returns an object that can be used to configure a property of the entity type where that property represents
/// a collection of primitive values, such as strings or integers.
/// If no property with the given name exists, then a new property will be added.
/// </summary>
/// <remarks>
/// When adding a new property with this overload the property name must match the
/// name of a CLR property or field on the entity type. This overload cannot be used to
/// add a new shadow state property.
/// </remarks>
/// <param name="propertyName">The name of the property to be configured.</param>
/// <returns>An object that can be used to configure the property.</returns>
public virtual PrimitiveCollectionBuilder PrimitiveCollection(string propertyName)
=> new(
Builder.Property(
Check.NotEmpty(propertyName, nameof(propertyName)), ConfigurationSource.Explicit)!
.HasElementType(ConfigurationSource.Explicit)!.Metadata);

/// <summary>
/// Returns an object that can be used to configure a property of the entity type where that property represents
/// a collection of primitive values, such as strings or integers.
/// If no property with the given name exists, then a new property will be added.
/// </summary>
/// <remarks>
/// When adding a new property, if a property with the same name exists in the entity class
/// then it will be added to the model. If no property exists in the entity class, then
/// a new shadow state property will be added. A shadow state property is one that does not have a
/// corresponding property in the entity class. The current value for the property is stored in
/// the <see cref="ChangeTracker" /> rather than being stored in instances of the entity class.
/// </remarks>
/// <typeparam name="TProperty">The type of the property to be configured.</typeparam>
/// <param name="propertyName">The name of the property to be configured.</param>
/// <returns>An object that can be used to configure the property.</returns>
public virtual PrimitiveCollectionBuilder<TProperty> PrimitiveCollection<TProperty>(string propertyName)
=> new(
Builder.Property(
typeof(TProperty),
Check.NotEmpty(propertyName, nameof(propertyName)), ConfigurationSource.Explicit)!
.HasElementType(ConfigurationSource.Explicit)!.Metadata);

/// <summary>
/// Returns an object that can be used to configure a property of the entity type where that property represents
/// a collection of primitive values, such as strings or integers.
/// If no property with the given name exists, then a new property will be added.
/// </summary>
/// <remarks>
/// When adding a new property, if a property with the same name exists in the entity class
/// then it will be added to the model. If no property exists in the entity class, then
/// a new shadow state property will be added. A shadow state property is one that does not have a
/// corresponding property in the entity class. The current value for the property is stored in
/// the <see cref="ChangeTracker" /> rather than being stored in instances of the entity class.
/// </remarks>
/// <param name="propertyType">The type of the property to be configured.</param>
/// <param name="propertyName">The name of the property to be configured.</param>
/// <returns>An object that can be used to configure the property.</returns>
public virtual PrimitiveCollectionBuilder PrimitiveCollection(Type propertyType, string propertyName)
=> new(
Builder.Property(
Check.NotNull(propertyType, nameof(propertyType)),
Check.NotEmpty(propertyName, nameof(propertyName)), ConfigurationSource.Explicit)!
.HasElementType(ConfigurationSource.Explicit)!.Metadata);

/// <summary>
/// Returns an object that can be used to configure a property of the entity type.
/// If no property with the given name exists, then a new property will be added.
Expand Down
15 changes: 15 additions & 0 deletions src/EFCore/Metadata/Builders/EntityTypeBuilder`.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,21 @@ public virtual PropertyBuilder<TProperty> Property<TProperty>(Expression<Func<TE
Check.NotNull(propertyExpression, nameof(propertyExpression)).GetMemberAccess(), ConfigurationSource.Explicit)!
.Metadata);

/// <summary>
/// Returns an object that can be used to configure a property of the entity type.
/// If the specified property is not already part of the model, it will be added.
/// </summary>
/// <param name="propertyExpression">
/// A lambda expression representing the property to be configured (
/// <c>blog => blog.Url</c>).
/// </param>
/// <returns>An object that can be used to configure the property.</returns>
public virtual PrimitiveCollectionBuilder<TProperty> PrimitiveCollection<TProperty>(
Expression<Func<TEntity, TProperty>> propertyExpression)
=> new(
Builder.Property(Check.NotNull(propertyExpression, nameof(propertyExpression)).GetMemberAccess(),
ConfigurationSource.Explicit)!.HasElementType(ConfigurationSource.Explicit)!.Metadata);

/// <summary>
/// Configures a complex property of the entity type.
/// If no property with the given name exists, then a new property will be added.
Expand Down
62 changes: 62 additions & 0 deletions src/EFCore/Metadata/Builders/OwnedNavigationBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,68 @@ public virtual PropertyBuilder Property(Type propertyType, string propertyName)
Check.NotNull(propertyType, nameof(propertyType)),
Check.NotEmpty(propertyName, nameof(propertyName)), ConfigurationSource.Explicit)!.Metadata);

/// <summary>
/// Returns an object that can be used to configure a property of the owned entity type.
/// If no property with the given name exists, then a new property will be added.
/// </summary>
/// <remarks>
/// When adding a new property with this overload the property name must match the
/// name of a CLR property or field on the entity type. This overload cannot be used to
/// add a new shadow state property.
/// </remarks>
/// <param name="propertyName">The name of the property to be configured.</param>
/// <returns>An object that can be used to configure the property.</returns>
public virtual PrimitiveCollectionBuilder PrimitiveCollection(string propertyName)
=> UpdateBuilder(
() => new PrimitiveCollectionBuilder(
DependentEntityType.Builder.Property(
Check.NotEmpty(propertyName, nameof(propertyName)),
ConfigurationSource.Explicit)!
.HasElementType(ConfigurationSource.Explicit)!.Metadata));

/// <summary>
/// Returns an object that can be used to configure a property of the owned entity type.
/// If no property with the given name exists, then a new property will be added.
/// </summary>
/// <remarks>
/// When adding a new property, if a property with the same name exists in the entity class
/// then it will be added to the model. If no property exists in the entity class, then
/// a new shadow state property will be added. A shadow state property is one that does not have a
/// corresponding property in the entity class. The current value for the property is stored in
/// the <see cref="ChangeTracker" /> rather than being stored in instances of the entity class.
/// </remarks>
/// <typeparam name="TProperty">The type of the property to be configured.</typeparam>
/// <param name="propertyName">The name of the property to be configured.</param>
/// <returns>An object that can be used to configure the property.</returns>
public virtual PrimitiveCollectionBuilder<TProperty> PrimitiveCollection<TProperty>(string propertyName)
=> UpdateBuilder(
() => new PrimitiveCollectionBuilder<TProperty>(
DependentEntityType.Builder.Property(
typeof(TProperty),
Check.NotEmpty(propertyName, nameof(propertyName)), ConfigurationSource.Explicit)!
.HasElementType(ConfigurationSource.Explicit)!.Metadata));

/// <summary>
/// Returns an object that can be used to configure a property of the owned entity type.
/// If no property with the given name exists, then a new property will be added.
/// </summary>
/// <remarks>
/// When adding a new property, if a property with the same name exists in the entity class
/// then it will be added to the model. If no property exists in the entity class, then
/// a new shadow state property will be added. A shadow state property is one that does not have a
/// corresponding property in the entity class. The current value for the property is stored in
/// the <see cref="ChangeTracker" /> rather than being stored in instances of the entity class.
/// </remarks>
/// <param name="propertyType">The type of the property to be configured.</param>
/// <param name="propertyName">The name of the property to be configured.</param>
/// <returns>An object that can be used to configure the property.</returns>
public virtual PrimitiveCollectionBuilder PrimitiveCollection(Type propertyType, string propertyName)
=> new(
DependentEntityType.Builder.Property(
Check.NotNull(propertyType, nameof(propertyType)), Check.NotEmpty(propertyName, nameof(propertyName)),
ConfigurationSource.Explicit)!
.HasElementType(ConfigurationSource.Explicit)!.Metadata);

/// <summary>
/// Returns an object that can be used to configure a property of the entity type.
/// If no property with the given name exists, then a new property will be added.
Expand Down
Loading

0 comments on commit 1e2a724

Please sign in to comment.