Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store all sequences in a single annotation #20066

Merged
merged 1 commit into from
Feb 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public virtual void Generate(string builderName, IModel model, IndentedStringBui
CoreAnnotationNames.ChangeTrackingStrategy,
CoreAnnotationNames.OwnedTypes,
RelationalAnnotationNames.CheckConstraints,
RelationalAnnotationNames.Sequences,
RelationalAnnotationNames.Tables,
RelationalAnnotationNames.Views);

Expand All @@ -81,6 +82,11 @@ public virtual void Generate(string builderName, IModel model, IndentedStringBui
stringBuilder.AppendLine(";");
}

foreach (var sequence in model.GetSequences())
{
GenerateSequence(builderName, sequence, stringBuilder);
}

GenerateEntityTypes(builderName, Sort(model.GetEntityTypes().Where(et => !et.IsIgnoredByMigrations()).ToList()), stringBuilder);
}

Expand Down Expand Up @@ -338,6 +344,93 @@ protected virtual void GenerateBaseType(
}
}

/// <summary>
/// Generates code for an <see cref="ISequence" />.
/// </summary>
/// <param name="builderName"> The name of the builder variable. </param>
/// <param name="sequence"> The sequence. </param>
/// <param name="stringBuilder"> The builder code is added to. </param>
protected virtual void GenerateSequence(
[NotNull] string builderName,
[NotNull] ISequence sequence,
[NotNull] IndentedStringBuilder stringBuilder)
{
stringBuilder
.AppendLine()
.Append(builderName)
.Append(".HasSequence");

if (sequence.ClrType != Sequence.DefaultClrType)
{
stringBuilder
.Append("<")
.Append(Code.Reference(sequence.ClrType))
.Append(">");
}

stringBuilder
.Append("(")
.Append(Code.Literal(sequence.Name));

if (!string.IsNullOrEmpty(sequence.Schema)
&& sequence.Model.GetDefaultSchema() != sequence.Schema)
{
stringBuilder
.Append(", ")
.Append(Code.Literal(sequence.Schema));
}

stringBuilder.Append(")");

using (stringBuilder.Indent())
{
if (sequence.StartValue != Sequence.DefaultStartValue)
{
stringBuilder
.AppendLine()
.Append(".StartsAt(")
.Append(Code.Literal(sequence.StartValue))
.Append(")");
}

if (sequence.IncrementBy != Sequence.DefaultIncrementBy)
{
stringBuilder
.AppendLine()
.Append(".IncrementsBy(")
.Append(Code.Literal(sequence.IncrementBy))
.Append(")");
}

if (sequence.MinValue != Sequence.DefaultMinValue)
{
stringBuilder
.AppendLine()
.Append(".HasMin(")
.Append(Code.Literal(sequence.MinValue))
.Append(")");
}

if (sequence.MaxValue != Sequence.DefaultMaxValue)
{
stringBuilder
.AppendLine()
.Append(".HasMax(")
.Append(Code.Literal(sequence.MaxValue))
.Append(")");
}

if (sequence.IsCyclic != Sequence.DefaultIsCyclic)
{
stringBuilder
.AppendLine()
.Append(".IsCyclic()");
}
}

stringBuilder.AppendLine(";");
}

/// <summary>
/// Generates code for <see cref="IProperty" /> objects.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ private IEnumerable<string> GetAnnotationNamespaces(IEnumerable<IAnnotatable> it
CoreAnnotationNames.DefiningQuery,
CoreAnnotationNames.QueryFilter,
RelationalAnnotationNames.CheckConstraints,
RelationalAnnotationNames.Sequences,
RelationalAnnotationNames.Tables,
RelationalAnnotationNames.TableMappings,
RelationalAnnotationNames.TableColumnMappings,
Expand All @@ -252,7 +253,7 @@ private IEnumerable<string> GetAnnotationNamespaces(IEnumerable<IAnnotatable> it

var ignoredAnnotationTypes = new List<string>
{
RelationalAnnotationNames.DbFunction, RelationalAnnotationNames.SequencePrefix
RelationalAnnotationNames.DbFunction
};

return items.SelectMany(
Expand Down
30 changes: 29 additions & 1 deletion src/EFCore.Design/Migrations/Internal/SnapshotModelProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata.Internal;

namespace Microsoft.EntityFrameworkCore.Migrations.Internal
Expand Down Expand Up @@ -61,6 +60,7 @@ public virtual IModel Process(IModel model)
if (version != null)
{
ProcessElement(model, version);
UpdateSequences(model, version);

foreach (var entityType in model.GetEntityTypes())
{
Expand Down Expand Up @@ -141,6 +141,34 @@ private void ProcessElement(IAnnotatable metadata, string version)
}
}

private void UpdateSequences(IModel model, string version)
{
if ((!version.StartsWith("1.", StringComparison.Ordinal)
&& !version.StartsWith("2.", StringComparison.Ordinal)
&& !version.StartsWith("3.", StringComparison.Ordinal))
|| !(model is IMutableModel mutableModel))
{
return;
}

var sequences = model.GetAnnotations()
#pragma warning disable CS0618 // Type or member is obsolete
.Where(a => a.Name.StartsWith(RelationalAnnotationNames.SequencePrefix, StringComparison.Ordinal))
.Select(a => new Sequence(model, a.Name));
#pragma warning restore CS0618 // Type or member is obsolete

var sequencesDictionary = new SortedDictionary<(string, string), Sequence>();
foreach (var sequence in sequences)
{
sequencesDictionary[(sequence.Name, sequence.Schema)] = sequence;
}

if (sequencesDictionary.Count > 0)
{
mutableModel[RelationalAnnotationNames.Sequences] = sequencesDictionary;
}
}

private void UpdateOwnedTypes(IMutableEntityType entityType)
{
var ownerships = entityType.GetDeclaredReferencingForeignKeys().Where(fk => fk.IsOwnership && fk.IsUnique)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,15 +263,13 @@ protected virtual void GenerateOnModelCreating(
RemoveAnnotation(ref annotations, ChangeDetector.SkipDetectChangesAnnotation);
RemoveAnnotation(ref annotations, RelationalAnnotationNames.MaxIdentifierLength);
RemoveAnnotation(ref annotations, RelationalAnnotationNames.CheckConstraints);
RemoveAnnotation(ref annotations, RelationalAnnotationNames.Sequences);
RemoveAnnotation(ref annotations, RelationalAnnotationNames.Tables);
RemoveAnnotation(ref annotations, RelationalAnnotationNames.Views);
RemoveAnnotation(ref annotations, ScaffoldingAnnotationNames.DatabaseName);
RemoveAnnotation(ref annotations, ScaffoldingAnnotationNames.EntityTypeErrors);

var annotationsToRemove = new List<IAnnotation>();
annotationsToRemove.AddRange(
annotations.Where(
a => a.Name.StartsWith(RelationalAnnotationNames.SequencePrefix, StringComparison.Ordinal)));

var lines = new List<string>();

Expand Down
23 changes: 11 additions & 12 deletions src/EFCore.Relational/Extensions/RelationalEntityTypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -449,29 +449,28 @@ public static bool IsIgnoredByMigrations([NotNull] this IEntityType entityType)
return entityType.BaseType.IsIgnoredByMigrations();
}

if (entityType.GetDefiningQuery() != null)
if (entityType.GetTableName() != null)
{
return true;
return false;
}

if (entityType.FindAnnotation(RelationalAnnotationNames.QueryableFunctionResultType) != null)
return true;

var viewDefinition = entityType.FindAnnotation(RelationalAnnotationNames.ViewDefinition);
if (viewDefinition == null)
if (viewDefinition?.Value != null)
{
var ownership = entityType.FindOwnership();
if (ownership != null
&& ownership.IsUnique
&& entityType.FindAnnotation(RelationalAnnotationNames.TableName) == null)
{
return ownership.PrincipalEntityType.IsIgnoredByMigrations();
}

return false;
}

return viewDefinition.Value == null;
var ownership = entityType.FindOwnership();
if (ownership != null
&& ownership.IsUnique)
{
return ownership.PrincipalEntityType.IsIgnoredByMigrations();
}

return true;
}
}
}
26 changes: 11 additions & 15 deletions src/EFCore.Relational/Extensions/RelationalModelExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,8 @@ public static void SetMaxIdentifierLength([NotNull] this IConventionModel model,
/// the given schema was found.
/// </returns>
public static ISequence FindSequence([NotNull] this IModel model, [NotNull] string name, [CanBeNull] string schema = null)
{
Check.NotEmpty(name, nameof(name));
Check.NullButNotEmpty(schema, nameof(schema));

return Sequence.FindSequence(model, name, schema);
}
=> Sequence.FindSequence(
Check.NotNull(model, nameof(model)), Check.NotEmpty(name, nameof(name)), Check.NullButNotEmpty(schema, nameof(schema)));

/// <summary>
/// Finds an <see cref="IMutableSequence" /> with the given name.
Expand Down Expand Up @@ -194,7 +190,7 @@ public static IConventionSequence FindSequence(
/// <returns> The sequence. </returns>
public static IMutableSequence AddSequence(
[NotNull] this IMutableModel model, [NotNull] string name, [CanBeNull] string schema = null)
=> new Sequence(model, name, schema, ConfigurationSource.Explicit);
=> Sequence.AddSequence(model, name, schema, ConfigurationSource.Explicit);

/// <summary>
/// Either returns the existing <see cref="IMutableSequence" /> with the given name in the given schema
Expand All @@ -207,7 +203,7 @@ public static IMutableSequence AddSequence(
/// <returns> The sequence. </returns>
public static IConventionSequence AddSequence(
[NotNull] this IConventionModel model, [NotNull] string name, [CanBeNull] string schema = null, bool fromDataAnnotation = false)
=> new Sequence(
=> Sequence.AddSequence(
(IMutableModel)model, name, schema,
fromDataAnnotation ? ConfigurationSource.DataAnnotation : ConfigurationSource.Convention);

Expand All @@ -223,7 +219,7 @@ public static IConventionSequence AddSequence(
/// </returns>
public static IMutableSequence RemoveSequence(
[NotNull] this IMutableModel model, [NotNull] string name, [CanBeNull] string schema = null)
=> (IMutableSequence)Sequence.RemoveSequence(model, name, schema);
=> Sequence.RemoveSequence(model, name, schema);

/// <summary>
/// Removes the <see cref="IConventionSequence" /> with the given name.
Expand All @@ -243,22 +239,22 @@ public static IConventionSequence RemoveSequence(
/// Returns all <see cref="ISequence" />s contained in the model.
/// </summary>
/// <param name="model"> The model to get the sequences in. </param>
public static IReadOnlyList<ISequence> GetSequences([NotNull] this IModel model)
=> Sequence.GetSequences(model, RelationalAnnotationNames.SequencePrefix).ToList();
public static IEnumerable<ISequence> GetSequences([NotNull] this IModel model)
=> Sequence.GetSequences(model);

/// <summary>
/// Returns all <see cref="IMutableSequence" />s contained in the model.
/// </summary>
/// <param name="model"> The model to get the sequences in. </param>
public static IReadOnlyList<IMutableSequence> GetSequences([NotNull] this IMutableModel model)
=> (IReadOnlyList<IMutableSequence>)((IModel)model).GetSequences();
public static IEnumerable<IMutableSequence> GetSequences([NotNull] this IMutableModel model)
=> (IEnumerable<IMutableSequence>)((IModel)model).GetSequences();

/// <summary>
/// Returns all <see cref="IConventionSequence" />s contained in the model.
/// </summary>
/// <param name="model"> The model to get the sequences in. </param>
public static IReadOnlyList<IConventionSequence> GetSequences([NotNull] this IConventionModel model)
=> (IReadOnlyList<IConventionSequence>)((IModel)model).GetSequences();
public static IEnumerable<IConventionSequence> GetSequences([NotNull] this IConventionModel model)
=> (IEnumerable<IConventionSequence>)((IModel)model).GetSequences();

/// <summary>
/// Finds a <see cref="IDbFunction" /> that is mapped to the method represented by the given <see cref="MethodInfo" />.
Expand Down
Loading