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

More triggers to Core #28700

Merged
1 commit merged into from
Aug 13, 2022
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
6 changes: 3 additions & 3 deletions src/EFCore.Design/Extensions/ScaffoldingModelExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -407,14 +407,14 @@ public static IEnumerable<AttributeCodeFragment> GetDataAnnotations(this ISkipNa
toTableNestedCalls.Add(new MethodCallCodeFragment(nameof(TableBuilder.HasComment), comment));
}

if (entityType.GetTriggers().Any())
if (entityType.GetDeclaredTriggers().Any())
{
toTableHandledByConventions = false;
toTableHandledByDataAnnotations = false;

foreach (var trigger in entityType.GetTriggers())
foreach (var trigger in entityType.GetDeclaredTriggers())
{
toTableNestedCalls.Add(new MethodCallCodeFragment(nameof(TableBuilder.HasTrigger), trigger.Name));
toTableNestedCalls.Add(new MethodCallCodeFragment(nameof(TableBuilder.HasTrigger), trigger.ModelName));
}
}

Expand Down
50 changes: 29 additions & 21 deletions src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Text;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;

namespace Microsoft.EntityFrameworkCore.Migrations.Design;
Expand Down Expand Up @@ -847,28 +849,28 @@ private void GenerateTableMapping(
annotations.TryGetAndRemove(RelationalAnnotationNames.TableName, out IAnnotation tableNameAnnotation);
var table = StoreObjectIdentifier.Create(entityType, StoreObjectType.Table);
var tableName = (string?)tableNameAnnotation?.Value ?? table?.Name;
var explicitName = tableNameAnnotation != null
|| entityType.BaseType == null
var explicitName = tableNameAnnotation != null
|| entityType.BaseType == null
|| entityType.BaseType.GetTableName() != tableName;

annotations.TryGetAndRemove(RelationalAnnotationNames.Schema, out IAnnotation schemaAnnotation);
var schema = (string?)schemaAnnotation?.Value ?? table?.Schema;

annotations.TryGetAndRemove(RelationalAnnotationNames.IsTableExcludedFromMigrations, out IAnnotation isExcludedAnnotation);
var isExcludedFromMigrations = (isExcludedAnnotation?.Value as bool?) == true;

annotations.TryGetAndRemove(RelationalAnnotationNames.Comment, out IAnnotation commentAnnotation);
var comment = (string?)commentAnnotation?.Value;
var hasTriggers = entityType.GetTriggers().Any(t => t.TableName == tableName! && t.TableSchema == schema);

var hasTriggers = entityType.GetDeclaredTriggers().Any(t => t.GetTableName() == tableName! && t.GetTableSchema() == schema);
var hasOverrides = table != null
&& entityType.GetProperties().Select(p => p.FindOverrides(table.Value)).Any(o => o != null);
var requiresTableBuilder = isExcludedFromMigrations
|| comment != null
|| hasTriggers
|| hasOverrides
|| entityType.GetCheckConstraints().Any();

if (!explicitName
&& !requiresTableBuilder)
{
Expand All @@ -879,7 +881,7 @@ private void GenerateTableMapping(
.AppendLine()
.Append(entityTypeBuilderName)
.Append(".ToTable(");

if (explicitName)
{
if (tableName == null
Expand Down Expand Up @@ -932,7 +934,7 @@ private void GenerateTableMapping(
.AppendLine()
.AppendLine("t.ExcludeFromMigrations();");
}

if (comment != null)
{
stringBuilder
Expand Down Expand Up @@ -1106,6 +1108,7 @@ protected virtual void GenerateEntityTypeMappingFragmentAnnotations(
var annotations = Dependencies.AnnotationCodeGenerator
.FilterIgnoredAnnotations(fragment.GetAnnotations())
.ToDictionary(a => a.Name, a => a);

if (annotations.Count > 0)
{
GenerateAnnotations(tableBuilderName, fragment, stringBuilder, annotations, inChainedCall: false);
Expand Down Expand Up @@ -1169,6 +1172,7 @@ protected virtual void GenerateCheckConstraintAnnotations(
var annotations = Dependencies.AnnotationCodeGenerator
.FilterIgnoredAnnotations(checkConstraint.GetAnnotations())
.ToDictionary(a => a.Name, a => a);

using (stringBuilder.Indent())
{
if (hasNonDefaultName)
Expand Down Expand Up @@ -1207,9 +1211,9 @@ protected virtual void GenerateTriggers(
string? schema,
IndentedStringBuilder stringBuilder)
{
foreach (var trigger in entityType.GetTriggers())
foreach (var trigger in entityType.GetDeclaredTriggers())
{
if (trigger.TableName != table || trigger.TableSchema != schema)
if (trigger.GetTableName() != table || trigger.GetTableSchema() != schema)
{
continue;
}
Expand Down Expand Up @@ -1237,15 +1241,6 @@ protected virtual void GenerateTrigger(
// Note that GenerateAnnotations below does the corresponding decrement
stringBuilder.IncrementIndent();

if (trigger.Name != trigger.GetDefaultName()!)
{
stringBuilder
.AppendLine()
.Append(".HasName(")
.Append(Code.Literal(trigger.Name))
.Append(")");
}

GenerateTriggerAnnotations(triggerBuilderName, trigger, stringBuilder);
}

Expand All @@ -1264,6 +1259,18 @@ protected virtual void GenerateTriggerAnnotations(
.FilterIgnoredAnnotations(trigger.GetAnnotations())
.ToDictionary(a => a.Name, a => a);

if (annotations.TryGetAndRemove(RelationalAnnotationNames.Name, out IAnnotation nameAnnotation))
{
stringBuilder
.AppendLine()
.Append(".HasName(")
.Append(Code.Literal((string?)nameAnnotation.Value))
.Append(")");
}

annotations.Remove(RelationalAnnotationNames.TableName);
annotations.Remove(RelationalAnnotationNames.Schema);

GenerateAnnotations(triggerBuilderName, trigger, stringBuilder, annotations, inChainedCall: true);
}

Expand Down Expand Up @@ -1337,6 +1344,7 @@ protected virtual void GeneratePropertyOverridesAnnotations(
var annotations = Dependencies.AnnotationCodeGenerator
.FilterIgnoredAnnotations(overrides.GetAnnotations())
.ToDictionary(a => a.Name, a => a);

GenerateAnnotations(propertyBuilderName, overrides, stringBuilder, annotations, inChainedCall: true);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,11 @@ private void CreateEntityType(
Create(index, propertyVariables, parameters, nullable);
}

foreach (var trigger in entityType.GetDeclaredTriggers())
{
Create(trigger, parameters);
}

mainBuilder
.Append("return ")
.Append(entityTypeVariable)
Expand Down Expand Up @@ -1322,6 +1327,26 @@ private void CreateSkipNavigation(
.AppendLine("}");
}

private void Create(ITrigger trigger, CSharpRuntimeAnnotationCodeGeneratorParameters parameters)
{
var triggerVariable = _code.Identifier(trigger.ModelName, parameters.ScopeVariables, capitalize: false);

var mainBuilder = parameters.MainBuilder;
mainBuilder
.Append("var ").Append(triggerVariable).Append(" = ").Append(parameters.TargetName).AppendLine(".AddTrigger(")
.IncrementIndent()
.Append(_code.Literal(trigger.ModelName))
.AppendLine(");")
.DecrementIndent();

CreateAnnotations(
trigger,
_annotationCodeGenerator.Generate,
parameters with { TargetName = triggerVariable });

mainBuilder.AppendLine();
}

private void CreateAnnotations(
IEntityType entityType,
IndentedStringBuilder mainBuilder,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,14 +335,9 @@ protected virtual ModelBuilder VisitTables(ModelBuilder modelBuilder, ICollectio
VisitUniqueConstraints(builder, table.UniqueConstraints);
VisitIndexes(builder, table.Indexes);

if (table.FindAnnotation(RelationalAnnotationNames.Triggers) is { Value: HashSet<string> triggers })
foreach (var triggerName in table.Triggers)
{
foreach (var triggerName in triggers)
{
builder.ToTable(table.Name, table.Schema, tb => tb.HasTrigger(triggerName));
}

table.RemoveAnnotation(RelationalAnnotationNames.Triggers);
builder.ToTable(table.Name, table.Schema, tb => tb.HasTrigger(triggerName));
}

builder.Metadata.AddAnnotations(table.GetAnnotations());
Expand Down
39 changes: 38 additions & 1 deletion src/EFCore.Relational/Design/AnnotationCodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ public class AnnotationCodeGenerator : IAnnotationCodeGenerator
private static readonly ISet<string> IgnoredRelationalAnnotations = new HashSet<string>
{
RelationalAnnotationNames.CheckConstraints,
RelationalAnnotationNames.Triggers,
RelationalAnnotationNames.Sequences,
RelationalAnnotationNames.DbFunctions,
RelationalAnnotationNames.DeleteStoredProcedure,
Expand Down Expand Up @@ -123,6 +122,18 @@ public virtual void RemoveAnnotationsHandledByConventions(
IDictionary<string, IAnnotation> annotations)
=> RemoveConventionalAnnotationsHelper(foreignKey, annotations, IsHandledByConvention);

/// <inheritdoc />
public virtual void RemoveAnnotationsHandledByConventions(
INavigation navigation,
IDictionary<string, IAnnotation> annotations)
=> RemoveConventionalAnnotationsHelper(navigation, annotations, IsHandledByConvention);

/// <inheritdoc />
public virtual void RemoveAnnotationsHandledByConventions(
ISkipNavigation navigation,
IDictionary<string, IAnnotation> annotations)
=> RemoveConventionalAnnotationsHelper(navigation, annotations, IsHandledByConvention);

/// <inheritdoc />
public virtual void RemoveAnnotationsHandledByConventions(IIndex index, IDictionary<string, IAnnotation> annotations)
=> RemoveConventionalAnnotationsHelper(index, annotations, IsHandledByConvention);
Expand Down Expand Up @@ -543,6 +554,32 @@ protected virtual bool IsHandledByConvention(IProperty property, IAnnotation ann
protected virtual bool IsHandledByConvention(IForeignKey foreignKey, IAnnotation annotation)
=> false;

/// <summary>
/// Checks if the given <paramref name="annotation" /> is handled by convention when
/// applied to the given <paramref name="navigation" />.
/// </summary>
/// <remarks>
/// The default implementation always returns <see langword="false" />.
/// </remarks>
/// <param name="navigation">The <see cref="INavigation" />.</param>
/// <param name="annotation">The <see cref="IAnnotation" />.</param>
/// <returns><see langword="false" />.</returns>
protected virtual bool IsHandledByConvention(INavigation navigation, IAnnotation annotation)
=> false;

/// <summary>
/// Checks if the given <paramref name="annotation" /> is handled by convention when
/// applied to the given <paramref name="navigation" />.
/// </summary>
/// <remarks>
/// The default implementation always returns <see langword="false" />.
/// </remarks>
/// <param name="navigation">The <see cref="ISkipNavigation" />.</param>
/// <param name="annotation">The <see cref="IAnnotation" />.</param>
/// <returns><see langword="false" />.</returns>
protected virtual bool IsHandledByConvention(ISkipNavigation navigation, IAnnotation annotation)
=> false;

/// <summary>
/// Checks if the given <paramref name="annotation" /> is handled by convention when
/// applied to the given <paramref name="index" />.
Expand Down
24 changes: 22 additions & 2 deletions src/EFCore.Relational/Design/IAnnotationCodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,26 @@ void RemoveAnnotationsHandledByConventions(IForeignKey foreignKey, IDictionary<s
{
}

/// <summary>
/// Removes annotation whose configuration is already applied by convention, and do not need to be
/// specified explicitly.
/// </summary>
/// <param name="navigation">The navigation to which the annotations are applied.</param>
/// <param name="annotations">The set of annotations from which to remove the conventional ones.</param>
void RemoveAnnotationsHandledByConventions(INavigation navigation, IDictionary<string, IAnnotation> annotations)
{
}

/// <summary>
/// Removes annotation whose configuration is already applied by convention, and do not need to be
/// specified explicitly.
/// </summary>
/// <param name="navigation">The navigation to which the annotations are applied.</param>
/// <param name="annotations">The set of annotations from which to remove the conventional ones.</param>
void RemoveAnnotationsHandledByConventions(ISkipNavigation navigation, IDictionary<string, IAnnotation> annotations)
{
}

/// <summary>
/// Removes annotation whose configuration is already applied by convention, and do not need to be
/// specified explicitly.
Expand Down Expand Up @@ -139,8 +159,8 @@ void RemoveAnnotationsHandledByConventions(ISequence sequence, IDictionary<strin
}

/// <summary>
/// For the given annotations which have corresponding fluent API calls, returns those fluent API calls
/// and removes the annotations.
/// Removes annotation whose configuration is already applied by convention, and do not need to be
/// specified explicitly.
/// </summary>
/// <param name="annotatable">The annotatable to which the annotations are applied.</param>
/// <param name="annotations">The set of annotations from which to generate fluent API calls.</param>
Expand Down
Loading