Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -1305,6 +1305,11 @@ private void GenerateSplitTableMapping(

using (stringBuilder.Indent())
{
if (fragment.IsOptional)
{
stringBuilder.AppendLine().Append("t.IsOptional();");
}

GenerateTriggers("t", entityType, table.Name, table.Schema, stringBuilder);
GeneratePropertyOverrides("t", entityType, table, stringBuilder);
GenerateEntityTypeMappingFragmentAnnotations("t", fragment, stringBuilder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1774,7 +1774,8 @@ private void GenerateAddMapping(
.Append($"{tableVariable}, {additionalParameter ?? ""}{code.Literal(tableMapping.IncludesDerivedTypes)}");

if (tableMapping.IsSharedTablePrincipal.HasValue
|| tableMapping.IsSplitEntityTypePrincipal.HasValue)
|| tableMapping.IsSplitEntityTypePrincipal.HasValue
|| tableMapping.IsSplitFragmentOptional)
{
mainBuilder.AppendLine(")")
.AppendLine("{").IncrementIndent();
Expand All @@ -1788,7 +1789,14 @@ private void GenerateAddMapping(
if (tableMapping.IsSplitEntityTypePrincipal.HasValue)
{
mainBuilder
.Append("IsSplitEntityTypePrincipal = ").AppendLine(code.Literal(tableMapping.IsSplitEntityTypePrincipal));
.Append("IsSplitEntityTypePrincipal = ").Append(code.Literal(tableMapping.IsSplitEntityTypePrincipal));
mainBuilder.AppendLine(tableMapping.IsSplitFragmentOptional ? "," : "");
}

if (tableMapping.IsSplitFragmentOptional)
{
mainBuilder
.Append("IsSplitFragmentOptional = ").AppendLine(code.Literal(tableMapping.IsSplitFragmentOptional));
}

mainBuilder.DecrementIndent().AppendLine("};");
Expand Down Expand Up @@ -2183,7 +2191,8 @@ private void Create(

AppendLiteral(storeObject, mainBuilder, code);
mainBuilder.AppendLine(",")
.Append(code.Literal(fragment.IsTableExcludedFromMigrations)).AppendLine(");").DecrementIndent();
.Append(code.Literal(fragment.IsTableExcludedFromMigrations)).AppendLine(",")
.Append(code.Literal(fragment.IsOptional)).AppendLine(");").DecrementIndent();

CreateAnnotations(
fragment,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace Microsoft.EntityFrameworkCore.Diagnostics;

/// <summary>
/// The <see cref="DiagnosticSource" /> event payload for events that reference an entity-splitting mapping fragment.
/// </summary>
public class EntityTypeMappingFragmentEventData : EventData
{
/// <summary>
/// Initializes a new instance of the <see cref="EntityTypeMappingFragmentEventData" /> class.
/// </summary>
/// <param name="eventDefinition">The event definition.</param>
/// <param name="messageGenerator">A delegate that generates a log message for this event.</param>
/// <param name="entityType">The entity type that owns the mapping fragment.</param>
/// <param name="storeObject">The store object for the mapping fragment.</param>
/// <param name="optional">A value indicating whether the fragment is now optional.</param>
public EntityTypeMappingFragmentEventData(
EventDefinitionBase eventDefinition,
Func<EventDefinitionBase, EventData, string> messageGenerator,
IEntityType entityType,
StoreObjectIdentifier storeObject,
bool optional)
: base(eventDefinition, messageGenerator)
{
EntityType = entityType;
StoreObject = storeObject;
IsOptional = optional;
}

/// <summary>
/// Gets the entity type that owns the mapping fragment.
/// </summary>
public virtual IEntityType EntityType { get; }

/// <summary>
/// Gets the store object for the mapping fragment.
/// </summary>
public virtual StoreObjectIdentifier StoreObject { get; }

/// <summary>
/// Gets a value indicating whether the fragment is now optional.
/// </summary>
public virtual bool IsOptional { get; }
}
16 changes: 16 additions & 0 deletions src/EFCore.Relational/Diagnostics/RelationalEventId.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ private enum Id
MigrationsUserTransactionWarning = CoreEventId.RelationalBaseId + 412,
ModelSnapshotNotFound = CoreEventId.RelationalBaseId + 413,
OldMigrationVersionWarning = CoreEventId.RelationalBaseId + 414,
EntitySplittingFragmentOptionalityChangedWarning = CoreEventId.RelationalBaseId + 415,

// Query events
QueryClientEvaluationWarning = CoreEventId.RelationalBaseId + 500,
Expand Down Expand Up @@ -821,6 +822,21 @@ private static EventId MakeMigrationsId(Id id)
/// </remarks>
public static readonly EventId OldMigrationVersionWarning = MakeMigrationsId(Id.OldMigrationVersionWarning);

/// <summary>
/// The optionality of an entity-splitting fragment changed since the last migration.
/// </summary>
/// <remarks>
/// <para>
/// This event is in the <see cref="DbLoggerCategory.Migrations" /> category.
/// </para>
/// <para>
/// This event uses the <see cref="EntityTypeMappingFragmentEventData" /> payload when used with a
/// <see cref="DiagnosticSource" />.
/// </para>
/// </remarks>
public static readonly EventId EntitySplittingFragmentOptionalityChangedWarning =
MakeMigrationsId(Id.EntitySplittingFragmentOptionalityChangedWarning);

private static readonly string _queryPrefix = DbLoggerCategory.Query.Name + ".";

private static EventId MakeQueryId(Id id)
Expand Down
46 changes: 46 additions & 0 deletions src/EFCore.Relational/Diagnostics/RelationalLoggerExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3700,6 +3700,52 @@ private static string ColumnOrderIgnoredWarning(EventDefinitionBase definition,
return d.GenerateMessage((p.ColumnOperation.Table, p.ColumnOperation.Schema).FormatTable(), p.ColumnOperation.Name);
}

/// <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>
public static void EntitySplittingFragmentOptionalityChangedWarning(
this IDiagnosticsLogger<DbLoggerCategory.Migrations> diagnostics,
IEntityType entityType,
StoreObjectIdentifier storeObject,
bool optional)
{
var definition = RelationalResources.LogEntitySplittingFragmentOptionalityChangedWarning(diagnostics);

if (diagnostics.ShouldLog(definition))
{
definition.Log(
diagnostics,
storeObject.DisplayName(),
entityType.DisplayName(),
optional ? "optional" : "required");
}

if (diagnostics.NeedsEventData(definition, out var diagnosticSourceEnabled, out var simpleLogEnabled))
{
var eventData = new EntityTypeMappingFragmentEventData(
definition,
EntitySplittingFragmentOptionalityChangedWarning,
entityType,
storeObject,
optional);

diagnostics.DispatchEventData(definition, eventData, diagnosticSourceEnabled, simpleLogEnabled);
}
}

private static string EntitySplittingFragmentOptionalityChangedWarning(EventDefinitionBase definition, EventData payload)
{
var d = (EventDefinition<string, string, string>)definition;
var p = (EntityTypeMappingFragmentEventData)payload;
return d.GenerateMessage(
p.StoreObject.DisplayName(),
p.EntityType.DisplayName(),
p.IsOptional ? "optional" : "required");
}

/// <summary>
/// Logs for the <see cref="RelationalEventId.UnexpectedTrailingResultSetWhenSaving" /> event.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,15 @@ public abstract class RelationalLoggingDefinitions : LoggingDefinitions
[EntityFrameworkInternal]
public EventDefinitionBase? LogColumnOrderIgnoredWarning;

/// <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 EventDefinitionBase? LogEntitySplittingFragmentOptionalityChangedWarning;

/// <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
Expand Down
76 changes: 75 additions & 1 deletion src/EFCore.Relational/EFCore.Relational.baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -2835,6 +2835,25 @@
}
]
},
{
"Type": "class Microsoft.EntityFrameworkCore.Diagnostics.EntityTypeMappingFragmentEventData : Microsoft.EntityFrameworkCore.Diagnostics.EventData",
"Methods": [
{
"Member": "EntityTypeMappingFragmentEventData(Microsoft.EntityFrameworkCore.Diagnostics.EventDefinitionBase eventDefinition, System.Func<Microsoft.EntityFrameworkCore.Diagnostics.EventDefinitionBase, Microsoft.EntityFrameworkCore.Diagnostics.EventData, string> messageGenerator, Microsoft.EntityFrameworkCore.Metadata.IEntityType entityType, Microsoft.EntityFrameworkCore.Metadata.StoreObjectIdentifier storeObject, bool optional);"
}
],
"Properties": [
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.IEntityType EntityType { get; }"
},
{
"Member": "virtual bool IsOptional { get; }"
},
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.StoreObjectIdentifier StoreObject { get; }"
}
]
},
{
"Type": "class Microsoft.EntityFrameworkCore.Diagnostics.EntityTypeSchemaEventData : Microsoft.EntityFrameworkCore.Diagnostics.EventData",
"Methods": [
Expand Down Expand Up @@ -3913,9 +3932,15 @@
{
"Member": "Microsoft.EntityFrameworkCore.Metadata.ConfigurationSource GetConfigurationSource();"
},
{
"Member": "Microsoft.EntityFrameworkCore.Metadata.ConfigurationSource? GetIsOptionalConfigurationSource();"
},
{
"Member": "Microsoft.EntityFrameworkCore.Metadata.ConfigurationSource? GetIsTableExcludedFromMigrationsConfigurationSource();"
},
{
"Member": "bool? SetIsOptional(bool? optional, bool fromDataAnnotation = false);"
},
{
"Member": "bool? SetIsTableExcludedFromMigrations(bool? excluded, bool fromDataAnnotation = false);"
}
Expand Down Expand Up @@ -5028,6 +5053,9 @@
{
"Member": "Microsoft.EntityFrameworkCore.Metadata.IMutableEntityType EntityType { get; }"
},
{
"Member": "bool IsOptional { get; set; }"
},
{
"Member": "bool? IsTableExcludedFromMigrations { get; set; }"
}
Expand Down Expand Up @@ -5606,6 +5634,9 @@
{
"Member": "Microsoft.EntityFrameworkCore.Metadata.IReadOnlyEntityType EntityType { get; }"
},
{
"Member": "bool IsOptional { get; }"
},
{
"Member": "bool? IsTableExcludedFromMigrations { get; }"
},
Expand Down Expand Up @@ -7189,6 +7220,9 @@
{
"Member": "bool? IsSplitEntityTypePrincipal { get; }"
},
{
"Member": "bool IsSplitFragmentOptional { get; }"
},
{
"Member": "Microsoft.EntityFrameworkCore.Metadata.ITableBase Table { get; }"
},
Expand Down Expand Up @@ -8524,6 +8558,15 @@
{
"Member": "virtual System.Collections.Generic.IReadOnlyList<Microsoft.EntityFrameworkCore.Update.IUpdateEntry> Entries { get; }"
},
{
"Member": "virtual bool IsOptionalSplitFragment { get; }"
},
{
"Member": "virtual bool IsOptionalSplitFragmentPayloadAllNull { get; }"
},
{
"Member": "virtual bool IsOptionalSplitFragmentRowAssumedAbsent { get; }"
},
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.IColumnBase? RowsAffectedColumn { get; private set; }"
},
Expand Down Expand Up @@ -8834,6 +8877,9 @@
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.TableTriggerBuilder HasTrigger(string modelName);"
},
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.OwnedNavigationSplitTableBuilder IsOptional(bool optional = true);"
},
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.ColumnBuilder Property(string propertyName);"
},
Expand Down Expand Up @@ -8868,6 +8914,9 @@
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.OwnedNavigationSplitTableBuilder<TOwnerEntity, TDependentEntity> HasAnnotation(string annotation, object? value);"
},
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.OwnedNavigationSplitTableBuilder<TOwnerEntity, TDependentEntity> IsOptional(bool optional = true);"
},
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.ColumnBuilder<TProperty> Property<TProperty>(System.Linq.Expressions.Expression<System.Func<TDependentEntity, TProperty>> propertyExpression);"
}
Expand Down Expand Up @@ -10006,6 +10055,10 @@
"Member": "const string DeleteStoredProcedureParameterMappings",
"Value": "Relational:DeleteStoredProcedureParameterMappings"
},
{
"Member": "const string EntityTypeMappingFragmentIsOptional",
"Value": "Relational:EntityTypeMappingFragmentIsOptional"
},
{
"Member": "const string FieldValueGetter",
"Value": "Relational:FieldValueGetter"
Expand Down Expand Up @@ -12727,6 +12780,9 @@
{
"Member": "static readonly Microsoft.Extensions.Logging.EventId DuplicateColumnOrders"
},
{
"Member": "static readonly Microsoft.Extensions.Logging.EventId EntitySplittingFragmentOptionalityChangedWarning"
},
{
"Member": "static readonly Microsoft.Extensions.Logging.EventId ExecuteDeleteFailed"
},
Expand Down Expand Up @@ -13454,6 +13510,9 @@
{
"Member": "static void DuplicateColumnOrders(this Microsoft.EntityFrameworkCore.Diagnostics.IDiagnosticsLogger<Microsoft.EntityFrameworkCore.DbLoggerCategory.Model.Validation> diagnostics, Microsoft.EntityFrameworkCore.Metadata.StoreObjectIdentifier storeObject, System.Collections.Generic.IReadOnlyList<string> columns);"
},
{
"Member": "static void EntitySplittingFragmentOptionalityChangedWarning(this Microsoft.EntityFrameworkCore.Diagnostics.IDiagnosticsLogger<Microsoft.EntityFrameworkCore.DbLoggerCategory.Migrations> diagnostics, Microsoft.EntityFrameworkCore.Metadata.IEntityType entityType, Microsoft.EntityFrameworkCore.Metadata.StoreObjectIdentifier storeObject, bool optional);"
},
{
"Member": "static void ExecuteDeleteFailed(this Microsoft.EntityFrameworkCore.Diagnostics.IDiagnosticsLogger<Microsoft.EntityFrameworkCore.DbLoggerCategory.Query> diagnostics, System.Type contextType, System.Exception exception);"
},
Expand Down Expand Up @@ -16519,6 +16578,12 @@
{
"Member": "static string EntitySplittingMissingRequiredPropertiesOptionalDependent(object? entityType, object? storeObject, object? requiredDependentConfig);"
},
{
"Member": "static string EntitySplittingNonNullablePropertyOnOptionalFragment(object? entityType, object? storeObject, object? property);"
},
{
"Member": "static string EntitySplittingOptionalFragmentSharedTable(object? entityType, object? storeObject, object? principalEntityType);"
},
{
"Member": "static string EntitySplittingUnmappedMainFragment(object? entityType, object? storeObject, object? storeObjectType);"
},
Expand Down Expand Up @@ -18368,7 +18433,7 @@
"Type": "class Microsoft.EntityFrameworkCore.Metadata.RuntimeEntityTypeMappingFragment : Microsoft.EntityFrameworkCore.Infrastructure.AnnotatableBase, Microsoft.EntityFrameworkCore.Metadata.IEntityTypeMappingFragment, Microsoft.EntityFrameworkCore.Metadata.IReadOnlyEntityTypeMappingFragment, Microsoft.EntityFrameworkCore.Infrastructure.IReadOnlyAnnotatable, Microsoft.EntityFrameworkCore.Infrastructure.IAnnotatable",
"Methods": [
{
"Member": "RuntimeEntityTypeMappingFragment(Microsoft.EntityFrameworkCore.Metadata.RuntimeEntityType entityType, in Microsoft.EntityFrameworkCore.Metadata.StoreObjectIdentifier storeObject, bool? isTableExcludedFromMigrations);"
"Member": "RuntimeEntityTypeMappingFragment(Microsoft.EntityFrameworkCore.Metadata.RuntimeEntityType entityType, in Microsoft.EntityFrameworkCore.Metadata.StoreObjectIdentifier storeObject, bool? isTableExcludedFromMigrations, bool isOptional = false);"
},
{
"Member": "override string ToString();"
Expand All @@ -18378,6 +18443,9 @@
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.RuntimeEntityType EntityType { get; }"
},
{
"Member": "virtual bool IsOptional { get; }"
},
{
"Member": "virtual bool? IsTableExcludedFromMigrations { get; }"
},
Expand Down Expand Up @@ -18931,6 +18999,9 @@
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.TableTriggerBuilder HasTrigger(string modelName);"
},
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.SplitTableBuilder IsOptional(bool optional = true);"
},
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.ColumnBuilder Property(string propertyName);"
},
Expand Down Expand Up @@ -18965,6 +19036,9 @@
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.SplitTableBuilder<TEntity> HasAnnotation(string annotation, object? value);"
},
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.SplitTableBuilder<TEntity> IsOptional(bool optional = true);"
},
{
"Member": "virtual Microsoft.EntityFrameworkCore.Metadata.Builders.ColumnBuilder<TProperty> Property<TProperty>(System.Linq.Expressions.Expression<System.Func<TEntity, TProperty>> propertyExpression);"
}
Expand Down
Loading
Loading