Skip to content

Commit

Permalink
Add a nested lambda to ToTable (#21847)
Browse files Browse the repository at this point in the history
Obsolete CoreAnnotationNames.DefiningQuery

Part of #20409
  • Loading branch information
AndriySvyryd committed Jul 29, 2020
1 parent eaf272b commit 2d5c580
Show file tree
Hide file tree
Showing 11 changed files with 172 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -805,8 +805,7 @@ protected virtual void GenerateEntityTypeAnnotations(
if (((bool?)isExcludedAnnotation.Value) == true)
{
stringBuilder
.Append(", ")
.Append(Code.Literal(true));
.Append(", t => t.IsExcludedFromMigrations()");
}
annotations.Remove(isExcludedAnnotation.Name);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ public static bool CanSetDefiningQuery(
[CanBeNull] LambdaExpression query,
bool fromDataAnnotation = false)
#pragma warning disable EF1001 // Internal EF Core API usage.
#pragma warning disable CS0612 // Type or member is obsolete
=> entityTypeBuilder.CanSetAnnotation(CoreAnnotationNames.DefiningQuery, query, fromDataAnnotation);
#pragma warning restore CS0612 // Type or member is obsolete
#pragma warning restore EF1001 // Internal EF Core API usage.
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ public static class InMemoryEntityTypeExtensions
/// <returns> The LINQ query used as the default source. </returns>
public static LambdaExpression GetDefiningQuery([NotNull] this IEntityType entityType)
#pragma warning disable EF1001 // Internal EF Core API usage.
#pragma warning disable CS0612 // Type or member is obsolete
=> (LambdaExpression)Check.NotNull(entityType, nameof(entityType))[CoreAnnotationNames.DefiningQuery];
#pragma warning restore CS0612 // Type or member is obsolete
#pragma warning restore EF1001 // Internal EF Core API usage.

/// <summary>
Expand All @@ -35,7 +37,9 @@ public static void SetDefiningQuery(
[CanBeNull] LambdaExpression definingQuery)
=> Check.NotNull(entityType, nameof(entityType))
#pragma warning disable EF1001 // Internal EF Core API usage.
#pragma warning disable CS0612 // Type or member is obsolete
.SetOrRemoveAnnotation(CoreAnnotationNames.DefiningQuery, definingQuery);
#pragma warning restore CS0612 // Type or member is obsolete
#pragma warning restore EF1001 // Internal EF Core API usage.

/// <summary>
Expand All @@ -51,7 +55,9 @@ public static LambdaExpression SetDefiningQuery(
bool fromDataAnnotation = false)
=> (LambdaExpression)Check.NotNull(entityType, nameof(entityType))
#pragma warning disable EF1001 // Internal EF Core API usage.
#pragma warning disable CS0612 // Type or member is obsolete
.SetOrRemoveAnnotation(CoreAnnotationNames.DefiningQuery, definingQuery, fromDataAnnotation)
#pragma warning restore CS0612 // Type or member is obsolete
#pragma warning restore EF1001 // Internal EF Core API usage.
?.Value;

Expand All @@ -62,7 +68,9 @@ public static LambdaExpression SetDefiningQuery(
/// <returns> The configuration source for <see cref="EntityTypeExtensions.GetDefiningQuery" />. </returns>
public static ConfigurationSource? GetDefiningQueryConfigurationSource([NotNull] this IConventionEntityType entityType)
#pragma warning disable EF1001 // Internal EF Core API usage.
#pragma warning disable CS0612 // Type or member is obsolete
=> entityType.FindAnnotation(CoreAnnotationNames.DefiningQuery)?.GetConfigurationSource();
#pragma warning restore CS0612 // Type or member is obsolete
#pragma warning restore EF1001 // Internal EF Core API usage.
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,20 @@ public static class RelationalEntityTypeBuilderExtensions
public static EntityTypeBuilder ToTable(
[NotNull] this EntityTypeBuilder entityTypeBuilder,
[CanBeNull] string name)
=> ToTable(entityTypeBuilder, name, excludedFromMigrations: false);
=> entityTypeBuilder.ToTable(name, (string)null);

/// <summary>
/// Configures the table that the entity type maps to when targeting a relational database.
/// </summary>
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param>
/// <param name="name"> The name of the table. </param>
/// <param name="excludedFromMigrations"> A value indicating whether the table should be managed by migrations. </param>
/// <param name="buildAction"> An action that performs configuration of the table. </param>
/// <returns> The same builder instance so that multiple calls can be chained. </returns>
public static EntityTypeBuilder ToTable(
[NotNull] this EntityTypeBuilder entityTypeBuilder,
[CanBeNull] string name,
bool excludedFromMigrations)
=> entityTypeBuilder.ToTable(name, null, excludedFromMigrations);
[NotNull] Action<TableBuilder> buildAction)
=> entityTypeBuilder.ToTable(name, null, buildAction);

/// <summary>
/// Configures the table that the entity type maps to when targeting a relational database.
Expand All @@ -53,22 +53,22 @@ public static EntityTypeBuilder<TEntity> ToTable<TEntity>(
[NotNull] this EntityTypeBuilder<TEntity> entityTypeBuilder,
[CanBeNull] string name)
where TEntity : class
=> (EntityTypeBuilder<TEntity>)ToTable((EntityTypeBuilder)entityTypeBuilder, name, excludedFromMigrations: false);
=> entityTypeBuilder.ToTable(name, (string)null);

/// <summary>
/// Configures the table that the entity type maps to when targeting a relational database.
/// </summary>
/// <typeparam name="TEntity"> The entity type being configured. </typeparam>
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param>
/// <param name="name"> The name of the table. </param>
/// <param name="excludedFromMigrations"> A value indicating whether the table should be managed by migrations. </param>
/// <param name="buildAction"> An action that performs configuration of the table. </param>
/// <returns> The same builder instance so that multiple calls can be chained. </returns>
public static EntityTypeBuilder<TEntity> ToTable<TEntity>(
[NotNull] this EntityTypeBuilder<TEntity> entityTypeBuilder,
[CanBeNull] string name,
bool excludedFromMigrations)
[NotNull] Action<TableBuilder<TEntity>> buildAction)
where TEntity : class
=> (EntityTypeBuilder<TEntity>)ToTable((EntityTypeBuilder)entityTypeBuilder, name, excludedFromMigrations);
=> entityTypeBuilder.ToTable(name, null, buildAction);

/// <summary>
/// Configures the table that the entity type maps to when targeting a relational database.
Expand All @@ -81,29 +81,32 @@ public static EntityTypeBuilder ToTable(
[NotNull] this EntityTypeBuilder entityTypeBuilder,
[CanBeNull] string name,
[CanBeNull] string schema)
=> entityTypeBuilder.ToTable(name, schema, excludedFromMigrations: false);
{
entityTypeBuilder.Metadata.SetTableName(name);
entityTypeBuilder.Metadata.SetSchema(schema);
return entityTypeBuilder;
}

/// <summary>
/// Configures the table that the entity type maps to when targeting a relational database.
/// </summary>
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param>
/// <param name="name"> The name of the table. </param>
/// <param name="schema"> The schema of the table. </param>
/// <param name="excludedFromMigrations"> A value indicating whether the table should be managed by migrations. </param>
/// <param name="buildAction"> An action that performs configuration of the table. </param>
/// <returns> The same builder instance so that multiple calls can be chained. </returns>
public static EntityTypeBuilder ToTable(
[NotNull] this EntityTypeBuilder entityTypeBuilder,
[CanBeNull] string name,
[CanBeNull] string schema,
bool excludedFromMigrations)
[NotNull] this EntityTypeBuilder entityTypeBuilder,
[NotNull] string name,
[CanBeNull] string schema,
[NotNull] Action<TableBuilder> buildAction)
{
Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder));
Check.NullButNotEmpty(name, nameof(name));
Check.NotNull(name, nameof(name));
Check.NullButNotEmpty(schema, nameof(schema));

buildAction(new TableBuilder(name, schema, entityTypeBuilder.Metadata));
entityTypeBuilder.Metadata.SetTableName(name);
entityTypeBuilder.Metadata.SetSchema(schema);
entityTypeBuilder.Metadata.SetIsTableExcludedFromMigrations(excludedFromMigrations);

return entityTypeBuilder;
}
Expand All @@ -121,7 +124,11 @@ public static EntityTypeBuilder<TEntity> ToTable<TEntity>(
[CanBeNull] string name,
[CanBeNull] string schema)
where TEntity : class
=> (EntityTypeBuilder<TEntity>)ToTable((EntityTypeBuilder)entityTypeBuilder, name, schema, excludedFromMigrations: false);
{
entityTypeBuilder.Metadata.SetTableName(name);
entityTypeBuilder.Metadata.SetSchema(schema);
return entityTypeBuilder;
}

/// <summary>
/// Configures the table that the entity type maps to when targeting a relational database.
Expand All @@ -130,15 +137,24 @@ public static EntityTypeBuilder<TEntity> ToTable<TEntity>(
/// <param name="entityTypeBuilder"> The builder for the entity type being configured. </param>
/// <param name="name"> The name of the table. </param>
/// <param name="schema"> The schema of the table. </param>
/// <param name="excludedFromMigrations"> A value indicating whether the table should be managed by migrations. </param>
/// <param name="buildAction"> An action that performs configuration of the table. </param>
/// <returns> The same builder instance so that multiple calls can be chained. </returns>
public static EntityTypeBuilder<TEntity> ToTable<TEntity>(
[NotNull] this EntityTypeBuilder<TEntity> entityTypeBuilder,
[CanBeNull] string name,
[CanBeNull] string schema,
bool excludedFromMigrations)
[NotNull] Action<TableBuilder<TEntity>> buildAction)
where TEntity : class
=> (EntityTypeBuilder<TEntity>)ToTable((EntityTypeBuilder)entityTypeBuilder, name, schema, excludedFromMigrations);
{
Check.NotNull(name, nameof(name));
Check.NullButNotEmpty(schema, nameof(schema));

buildAction(new TableBuilder<TEntity>(name, schema, entityTypeBuilder.Metadata));
entityTypeBuilder.Metadata.SetTableName(name);
entityTypeBuilder.Metadata.SetSchema(schema);

return entityTypeBuilder;
}

/// <summary>
/// Configures the table that the entity type maps to when targeting a relational database.
Expand Down
70 changes: 70 additions & 0 deletions src/EFCore.Relational/Metadata/Builders/TableBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// 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.ComponentModel;
using System.Diagnostics;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Infrastructure;

namespace Microsoft.EntityFrameworkCore.Metadata.Builders
{
/// <summary>
/// <para>
/// Instances of this class are returned from methods when using the <see cref="ModelBuilder" /> API
/// and it is not designed to be directly constructed in your application code.
/// </para>
/// </summary>
public class TableBuilder
{
/// <summary>
/// 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.
/// </summary>
[EntityFrameworkInternal]
public TableBuilder([NotNull] string name, [CanBeNull] string schema, [NotNull] IMutableEntityType entityType)
{
EntityType = entityType;
}

private IMutableEntityType EntityType { [DebuggerStepThrough] get; }

/// <summary>
/// Configures the table to be ignored by migrations.
/// </summary>
/// <param name="excluded"> A value indicating whether the table should be managed by migrations. </param>
/// <returns> The same builder instance so that multiple calls can be chained. </returns>
public virtual TableBuilder IsExcludedFromMigrations(bool excluded = true)
{
EntityType.SetIsTableExcludedFromMigrations(excluded);
return this;
}

#region Hidden System.Object members

/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns> A string that represents the current object. </returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override string ToString() => base.ToString();

/// <summary>
/// Determines whether the specified object is equal to the current object.
/// </summary>
/// <param name="obj"> The object to compare with the current object. </param>
/// <returns> <see langword="true"/> if the specified object is equal to the current object; otherwise, <see langword="false"/>. </returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool Equals(object obj) => base.Equals(obj);

/// <summary>
/// Serves as the default hash function.
/// </summary>
/// <returns> A hash code for the current object. </returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override int GetHashCode() => base.GetHashCode();

#endregion
}
}
39 changes: 39 additions & 0 deletions src/EFCore.Relational/Metadata/Builders/TableBuilder`.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// 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 JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Infrastructure;

namespace Microsoft.EntityFrameworkCore.Metadata.Builders
{
/// <summary>
/// <para>
/// Instances of this class are returned from methods when using the <see cref="ModelBuilder" /> API
/// and it is not designed to be directly constructed in your application code.
/// </para>
/// </summary>
/// <typeparam name="TEntity"> The entity type being configured. </typeparam>
public class TableBuilder<TEntity> : TableBuilder
where TEntity : class
{
/// <summary>
/// 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.
/// </summary>
[EntityFrameworkInternal]
public TableBuilder([NotNull] string name, [CanBeNull] string schema, [NotNull] IMutableEntityType entityType)
: base(name, schema, entityType)
{
}

/// <summary>
/// Configures the table to be ignored by migrations.
/// </summary>
/// <param name="excluded"> A value indicating whether the table should be managed by migrations. </param>
/// <returns> The same builder instance so that multiple calls can be chained. </returns>
public new virtual TableBuilder<TEntity> IsExcludedFromMigrations(bool excluded = true)
=> (TableBuilder<TEntity>)base.IsExcludedFromMigrations(excluded);
}
}
3 changes: 3 additions & 0 deletions src/EFCore/Metadata/Internal/CoreAnnotationNames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ public static class CoreAnnotationNames
/// 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.
/// </summary>
[Obsolete]
public const string DefiningQuery = "DefiningQuery";

/// <summary>
Expand Down Expand Up @@ -313,7 +314,9 @@ public static class CoreAnnotationNames
AfterSaveBehavior,
BeforeSaveBehavior,
QueryFilter,
#pragma warning disable CS0612 // Type or member is obsolete
DefiningQuery,
#pragma warning restore CS0612 // Type or member is obsolete
EagerLoaded,
ProviderClrType,
InverseNavigations,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,9 @@ public void Test_new_annotations_handled_for_properties()
CoreAnnotationNames.NavigationAccessMode,
CoreAnnotationNames.EagerLoaded,
CoreAnnotationNames.QueryFilter,
#pragma warning disable CS0612 // Type or member is obsolete
CoreAnnotationNames.DefiningQuery,
#pragma warning restore CS0612 // Type or member is obsolete
CoreAnnotationNames.DiscriminatorProperty,
CoreAnnotationNames.DiscriminatorValue,
CoreAnnotationNames.InverseNavigations,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ public virtual void Entities_are_stored_in_model_snapshot_for_TPT_with_one_exclu
builder =>
{
builder.Entity<DerivedEntity>()
.ToTable("DerivedEntity", "foo", excludedFromMigrations: true);
.ToTable("DerivedEntity", "foo", t => t.IsExcludedFromMigrations());
builder.Entity<BaseEntity>();
},
AddBoilerPlate(
Expand Down Expand Up @@ -462,7 +462,7 @@ public virtual void Entities_are_stored_in_model_snapshot_for_TPT_with_one_exclu
b.Property<string>(""Name"")
.HasColumnType(""nvarchar(max)"");
b.ToTable(""DerivedEntity"", ""foo"", true);
b.ToTable(""DerivedEntity"", ""foo"", t => t.IsExcludedFromMigrations());
});"),
o =>
{
Expand Down Expand Up @@ -704,7 +704,7 @@ public virtual void EntityType_annotations_are_stored_in_snapshot()
});"),
o =>
{
Assert.Equal(6, o.GetEntityTypes().First().GetAnnotations().Count());
Assert.Equal(5, o.GetEntityTypes().First().GetAnnotations().Count());
Assert.Equal("AnnotationValue", o.GetEntityTypes().First()["AnnotationName"]);
});
}
Expand Down
Loading

0 comments on commit 2d5c580

Please sign in to comment.