Skip to content

Commit

Permalink
Merge branch 'release/6.0' into release/7.0
Browse files Browse the repository at this point in the history
  • Loading branch information
ajcvickers committed Oct 5, 2023
2 parents a00b94e + 4a81376 commit 8fc207a
Show file tree
Hide file tree
Showing 23 changed files with 205 additions and 49 deletions.
8 changes: 6 additions & 2 deletions src/EFCore.Cosmos/Extensions/CosmosPropertyExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// 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.Linq;
using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal;

// ReSharper disable once CheckNamespace
Expand All @@ -15,7 +17,8 @@ namespace Microsoft.EntityFrameworkCore;
/// </remarks>
public static class CosmosPropertyExtensions
{
/// <summary>
private static readonly bool _useOldBehavior31664 =
AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue31664", out var enabled31664) && enabled31664;/// <summary>
/// Returns the property name that the property is mapped to when targeting Cosmos.
/// </summary>
/// <param name="property">The property.</param>
Expand All @@ -35,7 +38,8 @@ private static string GetDefaultJsonPropertyName(IReadOnlyProperty property)
var pk = property.FindContainingPrimaryKey();
if (pk != null
&& (property.ClrType == typeof(int) || ownership.Properties.Contains(property))
&& pk.Properties.Count == ownership.Properties.Count + (ownership.IsUnique ? 0 : 1)
&& (property.IsShadowProperty() || _useOldBehavior31664)
&& pk.Properties.Count == ownership.Properties.Count + (ownership.IsUnique ? 0 : 1)
&& ownership.Properties.All(fkProperty => pk.Properties.Contains(fkProperty)))
{
return "";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ public class CosmosValueGenerationConvention :
ValueGenerationConvention,
IEntityTypeAnnotationChangedConvention
{
/// <summary>
private static readonly bool _useOldBehavior31664 =
AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue31664", out var enabled31664) && enabled31664;/// <summary>
/// Creates a new instance of <see cref="CosmosValueGenerationConvention" />.
/// </summary>
/// <param name="dependencies">Parameter object containing dependencies for this convention.</param>
Expand Down Expand Up @@ -80,6 +81,7 @@ public virtual void ProcessEntityTypeAnnotationChanged(
if (pk != null
&& !property.IsForeignKey()
&& pk.Properties.Count == ownership.Properties.Count + 1
&& (property.IsShadowProperty() || _useOldBehavior31664)
&& ownership.Properties.All(fkProperty => pk.Properties.Contains(fkProperty)))
{
return ValueGenerated.OnAddOrUpdate;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ public static bool IsOrdinalKeyProperty(this IReadOnlyProperty property)
{
Check.DebugAssert(
property.DeclaringEntityType.IsOwned(), $"Expected {property.DeclaringEntityType.DisplayName()} to be owned.");
Check.DebugAssert(property.GetJsonPropertyName().Length == 0, $"Expected {property.Name} to be non-persisted.");

return property.FindContainingPrimaryKey() is IReadOnlyKey key
&& key.Properties.Count > 1
&& !property.IsForeignKey()
&& property.ClrType == typeof(int)
&& (property.ValueGenerated & ValueGenerated.OnAdd) != 0;
&& (property.ValueGenerated & ValueGenerated.OnAdd) != 0
&& property.GetJsonPropertyName().Length == 0;
}
}
2 changes: 1 addition & 1 deletion src/EFCore/ChangeTracking/Internal/ArrayPropertyValues.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public ArrayPropertyValues(InternalEntityEntry internalEntry, object?[] values)
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public override object ToObject()
=> MaterializerSource.GetMaterializer(EntityType)(
=> EntityType.GetOrCreateMaterializer(MaterializerSource)(
new MaterializationContext(
new ValueBuffer(_values),
InternalEntry.Context));
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore/ChangeTracking/Internal/StateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ public virtual InternalEntityEntry CreateEntry(IDictionary<string, object?> valu
}

var valueBuffer = new ValueBuffer(valuesArray);
var entity = EntityMaterializerSource.GetMaterializer(entityType)(new MaterializationContext(valueBuffer, Context));
var entity = entityType.GetOrCreateMaterializer(EntityMaterializerSource)(new MaterializationContext(valueBuffer, Context));

var shadowPropertyValueBuffer = new ValueBuffer(shadowPropertyValuesArray);
var entry = new InternalEntityEntry(this, entityType, entity, shadowPropertyValueBuffer);
Expand Down
13 changes: 7 additions & 6 deletions src/EFCore/Infrastructure/ModelValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -574,14 +574,15 @@ protected virtual void ValidateInheritanceMapping(
protected virtual void ValidateDiscriminatorValues(IEntityType rootEntityType)
{
var derivedTypes = rootEntityType.GetDerivedTypesInclusive().ToList();
if (derivedTypes.Count == 1)
{
return;
}


var discriminatorProperty = rootEntityType.FindDiscriminatorProperty();
if (discriminatorProperty == null)
{
if (discriminatorProperty == null){
if (derivedTypes.Count == 1)
{
return;
}

throw new InvalidOperationException(
CoreStrings.NoDiscriminatorProperty(rootEntityType.DisplayName()));
}
Expand Down
2 changes: 1 addition & 1 deletion src/EFCore/Metadata/Conventions/RuntimeModelConvention.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public virtual IModel ProcessModelFinalized(IModel model)
protected virtual RuntimeModel Create(IModel model)
{
var runtimeModel = new RuntimeModel();
runtimeModel.SetSkipDetectChanges(((IRuntimeModel)model).SkipDetectChanges);
runtimeModel.ModelId = model.ModelId;runtimeModel.SetSkipDetectChanges(((IRuntimeModel)model).SkipDetectChanges);
((IModel)runtimeModel).ModelDependencies = model.ModelDependencies!;

var entityTypes = model.GetEntityTypesInHierarchicalOrder();
Expand Down
28 changes: 28 additions & 0 deletions src/EFCore/Metadata/IReadOnlyEntityType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

using System.Text;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Utilities;

namespace Microsoft.EntityFrameworkCore.Metadata;

Expand Down Expand Up @@ -778,6 +781,31 @@ string ToDebugString(MetadataDebugStringOptions options = MetadataDebugStringOpt
{
var builder = new StringBuilder();
var indentString = new string(' ', indent);
/// <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]
Func<MaterializationContext, object> GetOrCreateMaterializer(IEntityMaterializerSource source);

/// <summary>
/// <para>
/// Creates a human-readable representation of the given metadata.
/// </para>
/// <para>
/// Warning: Do not rely on the format of the returned string.
/// It is designed for debugging only and may change arbitrarily between releases.
/// </para>
/// </summary>
/// <param name="options">Options for generating the string.</param>
/// <param name="indent">The number of indent spaces to use before each new line.</param>
/// <returns>A human-readable representation.</returns>
string ToDebugString(MetadataDebugStringOptions options = MetadataDebugStringOptions.ShortDefault, int indent = 0)
{
var builder = new StringBuilder();
var indentString = new string(' ', indent);

try
{
Expand Down
9 changes: 9 additions & 0 deletions src/EFCore/Metadata/IReadOnlyModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,15 @@ private static int GetDerivedLevel(Type? derivedType, Dictionary<Type, int> deri
}

/// <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 Guid ModelId { get; }

/// <summary>
/// <para>
/// Creates a human-readable representation of the given metadata.
/// </para>
Expand Down
17 changes: 16 additions & 1 deletion src/EFCore/Metadata/Internal/EntityType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Microsoft.EntityFrameworkCore.Utilities;

namespace Microsoft.EntityFrameworkCore.Metadata.Internal;

Expand Down Expand Up @@ -3574,7 +3579,17 @@ private void UpdateServiceOnlyConstructorBindingConfigurationSource(Configuratio
=> _serviceOnlyConstructorBindingConfigurationSource =
configurationSource.Max(_serviceOnlyConstructorBindingConfigurationSource);

#endregion
/// <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 virtual Func<MaterializationContext, object> GetOrCreateMaterializer(IEntityMaterializerSource source)
=> source.GetMaterializer(this);

#endregion

#region Explicit interface implementations

Expand Down
8 changes: 8 additions & 0 deletions src/EFCore/Metadata/Internal/Model.cs
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,14 @@ public virtual IEnumerable<EntityType> FindEntityTypes(Type type)
}

/// <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 virtual Guid ModelId { get; } = Guid.NewGuid();

/// <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
Expand Down
20 changes: 20 additions & 0 deletions src/EFCore/Metadata/RuntimeEntityType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Query.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Microsoft.EntityFrameworkCore.ValueGeneration;

namespace Microsoft.EntityFrameworkCore.Metadata;

Expand Down Expand Up @@ -65,6 +70,7 @@ private readonly SortedDictionary<string, RuntimeTrigger> _triggers
private Func<ISnapshot>? _emptyShadowValuesFactory;
private IProperty[]? _foreignKeyProperties;
private IProperty[]? _valueGeneratingProperties;
private Func<MaterializationContext, object>? _materializer;

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand Down Expand Up @@ -844,6 +850,20 @@ public virtual InstantiationBinding? ServiceOnlyConstructorBinding
=> type.FindIndexerProperty();

/// <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 virtual Func<MaterializationContext, object> GetOrCreateMaterializer(IEntityMaterializerSource source)
=> EntityMaterializerSource.UseOldBehavior31866
? source.GetMaterializer(this)
: NonCapturingLazyInitializer.EnsureInitialized(
ref _materializer, this, source,
static (e, s) => s.GetMaterializer(e));

/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>A string that represents the current object.</returns>
Expand Down
19 changes: 19 additions & 0 deletions src/EFCore/Metadata/RuntimeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,15 @@ private IEnumerable<RuntimeEntityType> FindEntityTypes(Type type)
}

/// <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 virtual Guid ModelId { get; set; }

/// <summary>
/// Adds configuration for a scalar type.
/// </summary>
/// <param name="clrType">The type of value the property will hold.</param>
Expand Down Expand Up @@ -302,4 +311,14 @@ IEnumerable<ITypeMappingConfiguration> IModel.GetTypeMappingConfigurations()
=> _typeConfigurations.Count == 0
? null
: _typeConfigurations.GetValueOrDefault(propertyType);
/// <inheritdoc />
ITypeMappingConfiguration? IModel.FindTypeMappingConfiguration(Type propertyType)
=> _typeConfigurations.Count == 0
? null
: _typeConfigurations.GetValueOrDefault(propertyType);

/// <inheritdoc />
Guid IReadOnlyModel.ModelId
=> ModelId;
}
}
2 changes: 1 addition & 1 deletion src/EFCore/Properties/CoreStrings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/EFCore/Properties/CoreStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1065,7 +1065,7 @@
<value>The entity type '{entityType}' is part of a hierarchy, but does not have a discriminator property configured.</value>
</data>
<data name="NoDiscriminatorValue" xml:space="preserve">
<value>The entity type '{entityType}' is part of a hierarchy, but does not have a discriminator value configured.</value>
<value>The entity type '{entityType}' has a discriminator property, but does not have a discriminator value configured.</value>
</data>
<data name="NoEfServices" xml:space="preserve">
<value>Entity Framework services have not been added to the internal service provider. Either remove the call to 'UseInternalServiceProvider' so that Entity Framework will manage its own internal services, or use the method from your database provider to add the required services to the service provider (e.g. 'AddEntityFrameworkSqlServer').</value>
Expand Down
39 changes: 27 additions & 12 deletions src/EFCore/Query/Internal/EntityMaterializerSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@ namespace Microsoft.EntityFrameworkCore.Query.Internal;
/// </summary>
public class EntityMaterializerSource : IEntityMaterializerSource
{
private ConcurrentDictionary<IEntityType, Func<MaterializationContext, object>>? _materializers;
/// <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 readonly bool UseOldBehavior31866 =
AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue31866", out var enabled31866) && enabled31866;private ConcurrentDictionary<IEntityType, Func<MaterializationContext, object>>? _materializers;
private ConcurrentDictionary<IEntityType, Func<MaterializationContext, object>>? _emptyMaterializers;
private readonly List<IInstantiationBindingInterceptor> _bindingInterceptors;
private readonly IMaterializationInterceptor? _materializationInterceptor;
Expand Down Expand Up @@ -355,21 +362,29 @@ private ConcurrentDictionary<IEntityType, Func<MaterializationContext, object>>
ref _materializers,
() => new ConcurrentDictionary<IEntityType, Func<MaterializationContext, object>>());

/// <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 virtual Func<MaterializationContext, object> GetMaterializer(
IEntityType entityType)
=> Materializers.GetOrAdd(
entityType,
static (e, self) =>
/// <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 virtual Func<MaterializationContext, object> GetMaterializer(IEntityType entityType)
{
return UseOldBehavior31866
? Materializers.GetOrAdd(entityType, static (e, s) => CreateMaterializer(s, e), this)
: CreateMaterializer(this, entityType);

static Func<MaterializationContext, object> CreateMaterializer(EntityMaterializerSource self, IEntityType e)
{
var materializationContextParameter
= Expression.Parameter(typeof(MaterializationContext), "materializationContext");

return Expression.Lambda<Func<MaterializationContext, object>>(
self.CreateMaterializeExpression(e, "instance", materializationContextParameter),
materializationContextParameter)
.Compile();
}
}
return Expression.Lambda<Func<MaterializationContext, object>>(
self.CreateMaterializeExpression(e, "instance", materializationContextParameter),
materializationContextParameter)
Expand Down
Loading

0 comments on commit 8fc207a

Please sign in to comment.