Skip to content

Commit

Permalink
Merge branch 'release/8.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
ajcvickers committed Oct 5, 2023
2 parents 16440a4 + b17b3af commit 1cd05c7
Show file tree
Hide file tree
Showing 121 changed files with 5,109 additions and 4,208 deletions.
1 change: 1 addition & 0 deletions src/EFCore.Cosmos/Extensions/CosmosPropertyExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ private static string GetDefaultJsonPropertyName(IReadOnlyProperty property)
var pk = property.FindContainingPrimaryKey();
if (pk != null
&& (property.ClrType == typeof(int) || ownership.Properties.Contains(property))
&& property.IsShadowProperty()
&& pk.Properties.Count == ownership.Properties.Count + (ownership.IsUnique ? 0 : 1)
&& ownership.Properties.All(fkProperty => pk.Properties.Contains(fkProperty)))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public virtual void ProcessEntityTypeAnnotationChanged(
if (pk != null
&& !property.IsForeignKey()
&& pk.Properties.Count == ownership.Properties.Count + 1
&& property.IsShadowProperty()
&& 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,11 +21,11 @@ public static bool IsOrdinalKeyProperty(this IReadOnlyProperty property)
{
Check.DebugAssert(
(property.DeclaringType as IEntityType)?.IsOwned() == true, $"Expected {property.DeclaringType.DisplayName()} to be owned.");
Check.DebugAssert(property.GetJsonPropertyName().Length == 0, $"Expected {property.Name} to be non-persisted.");

return property.FindContainingPrimaryKey() is { Properties.Count: > 1 }
return property.ClrType == typeof(int)
&& !property.IsForeignKey()
&& property.ClrType == typeof(int)
&& (property.ValueGenerated & ValueGenerated.OnAdd) != 0;
&& (property.ValueGenerated & ValueGenerated.OnAdd) != 0
&& property.FindContainingPrimaryKey() is { Properties.Count: > 1 }
&& property.GetJsonPropertyName().Length == 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,10 @@ private string CreateModel(
mainBuilder
.Append("[DbContext(typeof(").Append(_code.Reference(contextType)).AppendLine("))]")
.Append("public partial class ").Append(className).AppendLine(" : " + nameof(RuntimeModel))
.AppendLine("{");
.AppendLine("{")
.AppendLine(" private static readonly bool _useOldBehavior31751 =")
.AppendLine(@" System.AppContext.TryGetSwitch(""Microsoft.EntityFrameworkCore.Issue31751"", out var enabled31751) && enabled31751;")
.AppendLine();

using (mainBuilder.Indent())
{
Expand All @@ -153,7 +156,23 @@ private string CreateModel(
var model = new "
+ className
+ @"();
model.Initialize();
if (_useOldBehavior31751)
{
model.Initialize();
}
else
{
var thread = new System.Threading.Thread(RunInitialization, 10 * 1024 * 1024);
thread.Start();
thread.Join();
void RunInitialization()
{
model.Initialize();
}
}
model.Customize();
_instance = model;
}")
Expand Down Expand Up @@ -837,26 +856,13 @@ private void Create(
}

var sentinel = property.Sentinel;
if (sentinel != null)
var converter = property.FindTypeMapping()?.Converter;
if (sentinel != null
&& converter == null)
{
mainBuilder.AppendLine(",")
.Append("sentinel: ");

if (valueConverterType != null)
{
var converter = property.GetValueConverter()!;
mainBuilder.Append("new ")
.Append(_code.Reference(valueConverterType))
.Append("().")
.Append(nameof(ValueConverter.ConvertFromProvider))
.Append("(")
.Append(_code.UnknownLiteral(converter.ConvertToProvider(sentinel)))
.Append(")");
}
else
{
mainBuilder.Append(_code.UnknownLiteral(sentinel));
}
.Append("sentinel: ")
.Append(_code.UnknownLiteral(sentinel));
}

var jsonValueReaderWriterType = (Type?)property[CoreAnnotationNames.JsonValueReaderWriterType];
Expand All @@ -875,6 +881,14 @@ private void Create(
mainBuilder.Append(variableName).Append(".TypeMapping = ");
_annotationCodeGenerator.Create(property.GetTypeMapping(), property, parameters with { TargetName = variableName });
mainBuilder.AppendLine(";");

if (sentinel != null
&& converter != null)
{
mainBuilder.Append(variableName).Append(".SetSentinelFromProviderValue(")
.Append(_code.UnknownLiteral(converter?.ConvertToProvider(sentinel) ?? sentinel))
.AppendLine(");");
}
}

private static Type? GetValueConverterType(IProperty property)
Expand Down
20 changes: 20 additions & 0 deletions src/EFCore.Relational/Extensions/TableExpressionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.EntityFrameworkCore.Query.SqlExpressions;

// ReSharper disable once CheckNamespace
namespace Microsoft.EntityFrameworkCore;

/// <summary>
/// Type extension methods for <see cref="TableExpressionBase" /> and related types.
/// </summary>
public static class TableExpressionExtensions
{
/// <summary>
/// If the given <paramref name="table" /> is a <see cref="JoinExpressionBase" />, returns the table it joins to. Otherwise, returns
/// <paramref name="table" />.
/// </summary>
public static TableExpressionBase UnwrapJoin(this TableExpressionBase table)
=> table is JoinExpressionBase join ? join.Table : table;
}
13 changes: 5 additions & 8 deletions src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1863,11 +1863,6 @@ protected override void ValidateInheritanceMapping(
continue;
}

if (!entityType.GetDirectlyDerivedTypes().Any())
{
continue;
}

// Hierarchy mapping strategy must be the same across all types of mappings
if (entityType.FindDiscriminatorProperty() != null)
{
Expand All @@ -1890,7 +1885,8 @@ protected override void ValidateInheritanceMapping(
else
{
if (mappingStrategy != RelationalAnnotationNames.TpcMappingStrategy
&& entityType.FindPrimaryKey() == null)
&& entityType.FindPrimaryKey() == null
&& entityType.GetDirectlyDerivedTypes().Any())
{
throw new InvalidOperationException(
RelationalStrings.KeylessMappingStrategy(
Expand All @@ -1907,12 +1903,13 @@ protected override void ValidateInheritanceMapping(
var discriminatorValues = new Dictionary<string, IEntityType>();
foreach (var derivedType in derivedTypes)
{
if (!derivedType.ClrType.IsInstantiable())
var discriminatorValue = derivedType.GetDiscriminatorValue();
if (!derivedType.ClrType.IsInstantiable()
|| discriminatorValue is null)
{
continue;
}

var discriminatorValue = derivedType.GetDiscriminatorValue();
if (discriminatorValue is not string valueString)
{
throw new InvalidOperationException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -992,6 +992,7 @@ private static void IncludeJsonEntityCollection<TIncludingEntity, TIncludedColle
JsonReaderData? jsonReaderData,
TIncludingEntity entity,
Func<QueryContext, object[], JsonReaderData, TIncludedCollectionElement> innerShaper,
Action<TIncludingEntity> getOrCreateCollectionObject,
Action<TIncludingEntity, TIncludedCollectionElement> fixup,
bool trackingQuery)
where TIncludingEntity : class
Expand All @@ -1011,6 +1012,8 @@ private static void IncludeJsonEntityCollection<TIncludingEntity, TIncludedColle
RelationalStrings.JsonReaderInvalidTokenType(tokenType.ToString()));
}

getOrCreateCollectionObject(entity);

var newKeyPropertyValues = new object[keyPropertyValues.Length + 1];
Array.Copy(keyPropertyValues, newKeyPropertyValues, keyPropertyValues.Length);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ private static readonly MemberInfo ResultContextValuesMemberInfo
private static readonly MemberInfo SingleQueryResultCoordinatorResultReadyMemberInfo
= typeof(SingleQueryResultCoordinator).GetMember(nameof(SingleQueryResultCoordinator.ResultReady))[0];

private static readonly MethodInfo CollectionAccessorGetOrCreateMethodInfo
= typeof(IClrCollectionAccessor).GetTypeInfo().GetDeclaredMethod(nameof(IClrCollectionAccessor.GetOrCreate))!;

private static readonly MethodInfo CollectionAccessorAddMethodInfo
= typeof(IClrCollectionAccessor).GetTypeInfo().GetDeclaredMethod(nameof(IClrCollectionAccessor.Add))!;

Expand Down Expand Up @@ -1281,6 +1284,7 @@ private Expression CreateJsonShapers(

var innerShapersMap = new Dictionary<string, Expression>();
var innerFixupMap = new Dictionary<string, LambdaExpression>();
var trackingInnerFixupMap = new Dictionary<string, LambdaExpression>();
foreach (var ownedNavigation in entityType.GetNavigations().Where(
n => n.TargetEntityType.IsMappedToJson() && n.ForeignKey.IsOwnership && n == n.ForeignKey.PrincipalToDependent))
{
Expand All @@ -1303,21 +1307,30 @@ private Expression CreateJsonShapers(
var shaperEntityParameter = Parameter(ownedNavigation.DeclaringEntityType.ClrType);
var shaperCollectionParameter = Parameter(ownedNavigation.ClrType);
var expressions = new List<Expression>();
var expressionsForTracking = new List<Expression>();

if (!ownedNavigation.IsShadowProperty())
{
expressions.Add(
shaperEntityParameter.MakeMemberAccess(ownedNavigation.GetMemberInfo(forMaterialization: true, forSet: true))
.Assign(shaperCollectionParameter));

expressionsForTracking.Add(
IfThen(
OrElse(
ReferenceEqual(Constant(null), shaperCollectionParameter),
IsFalse(
Call(
typeof(EnumerableExtensions).GetMethod(nameof(EnumerableExtensions.Any))!,
shaperCollectionParameter))),
shaperEntityParameter
.MakeMemberAccess(ownedNavigation.GetMemberInfo(forMaterialization: true, forSet: true))
.Assign(shaperCollectionParameter)));
}

if (ownedNavigation.Inverse is INavigation inverseNavigation
&& !inverseNavigation.IsShadowProperty())
{
//for (var i = 0; i < prm.Count; i++)
//{
// prm[i].Parent = instance
//}
var innerFixupCollectionElementParameter = Parameter(inverseNavigation.DeclaringEntityType.ClrType);
var innerFixupParentParameter = Parameter(inverseNavigation.TargetEntityType.ClrType);

Expand Down Expand Up @@ -1347,6 +1360,14 @@ private Expression CreateJsonShapers(
shaperCollectionParameter);

innerFixupMap[navigationJsonPropertyName] = fixup;

var trackedFixup = Lambda(
Block(typeof(void), expressionsForTracking),
shaperEntityParameter,
shaperCollectionParameter);

innerFixupMap[navigationJsonPropertyName] = fixup;
trackingInnerFixupMap[navigationJsonPropertyName] = trackedFixup;
}
else
{
Expand All @@ -1366,6 +1387,7 @@ private Expression CreateJsonShapers(
jsonReaderDataShaperLambdaParameter,
innerShapersMap,
innerFixupMap,
trackingInnerFixupMap,
_queryLogger).Rewrite(entityShaperMaterializer);

var entityShaperMaterializerVariable = Variable(
Expand Down Expand Up @@ -1416,6 +1438,9 @@ private Expression CreateJsonShapers(
jsonReaderDataParameter,
includingEntityExpression,
shaperLambda,
GetOrCreateCollectionObjectLambda(
navigation.DeclaringEntityType.ClrType,
navigation),
fixup,
Constant(_isTracking));

Expand Down Expand Up @@ -1484,6 +1509,7 @@ private sealed class JsonEntityMaterializerRewriter : ExpressionVisitor
private readonly ParameterExpression _jsonReaderDataParameter;
private readonly IDictionary<string, Expression> _innerShapersMap;
private readonly IDictionary<string, LambdaExpression> _innerFixupMap;
private readonly IDictionary<string, LambdaExpression> _trackingInnerFixupMap;
private readonly IDiagnosticsLogger<DbLoggerCategory.Query> _queryLogger;

private static readonly PropertyInfo JsonEncodedTextEncodedUtf8BytesProperty
Expand All @@ -1499,13 +1525,15 @@ public JsonEntityMaterializerRewriter(
ParameterExpression jsonReaderDataParameter,
IDictionary<string, Expression> innerShapersMap,
IDictionary<string, LambdaExpression> innerFixupMap,
IDictionary<string, LambdaExpression> trackingInnerFixupMap,
IDiagnosticsLogger<DbLoggerCategory.Query> queryLogger)
{
_entityType = entityType;
_isTracking = isTracking;
_jsonReaderDataParameter = jsonReaderDataParameter;
_innerShapersMap = innerShapersMap;
_innerFixupMap = innerFixupMap;
_trackingInnerFixupMap = trackingInnerFixupMap;
_queryLogger = queryLogger;
}

Expand Down Expand Up @@ -1662,10 +1690,26 @@ protected override Expression VisitSwitch(SwitchExpression switchExpression)
finalBlockExpressions.Add(propertyAssignmentReplacer.Visit(jsonEntityTypeInitializerBlockExpression));
}

// fixup is only needed for non-tracking queries, in case of tracking - ChangeTracker does the job
if (!_isTracking)
// Fixup is only needed for non-tracking queries, in case of tracking - ChangeTracker does the job
// or for empty/null collections of a tracking queries.
if (_isTracking)
{
ProcessFixup(_trackingInnerFixupMap);
}
else
{
ProcessFixup(_innerFixupMap);
}

finalBlockExpressions.Add(jsonEntityTypeVariable);

return Block(
finalBlockVariables,
finalBlockExpressions);

void ProcessFixup(IDictionary<string, LambdaExpression> fixupMap)
{
foreach (var fixup in _innerFixupMap)
foreach (var fixup in fixupMap)
{
var navigationEntityParameter = _navigationVariableMap[fixup.Key];

Expand All @@ -1674,25 +1718,15 @@ protected override Expression VisitSwitch(SwitchExpression switchExpression)
// but in this case fixups are standalone, so the null safety must be added by us directly
finalBlockExpressions.Add(
IfThen(
AndAlso(
NotEqual(
jsonEntityTypeVariable,
Constant(null, jsonEntityTypeVariable.Type)),
NotEqual(
navigationEntityParameter,
Constant(null, navigationEntityParameter.Type))),
NotEqual(
jsonEntityTypeVariable,
Constant(null, jsonEntityTypeVariable.Type)),
Invoke(
fixup.Value,
jsonEntityTypeVariable,
_navigationVariableMap[fixup.Key])));
}
}

finalBlockExpressions.Add(jsonEntityTypeVariable);

return Block(
finalBlockVariables,
finalBlockExpressions);
}

return base.VisitSwitch(switchExpression);
Expand Down Expand Up @@ -2369,6 +2403,23 @@ private static Expression AssignReferenceNavigation(
INavigationBase navigation)
=> entity.MakeMemberAccess(navigation.GetMemberInfo(forMaterialization: true, forSet: true)).Assign(relatedEntity);

private static Expression GetOrCreateCollectionObjectLambda(
Type entityType,
INavigationBase navigation)
{
var prm = Parameter(entityType);

return Lambda(
Block(
typeof(void),
Call(
Constant(navigation.GetCollectionAccessor()),
CollectionAccessorGetOrCreateMethodInfo,
prm,
Constant(true))),
prm);
}

private static Expression AddToCollectionNavigation(
ParameterExpression entity,
ParameterExpression relatedEntity,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1112,7 +1112,7 @@ SqlExpression GeneratePredicateTpt(StructuralTypeProjectionExpression entityProj
return matchingCaseWhenClauses.Count == 1
? matchingCaseWhenClauses[0].Test
: matchingCaseWhenClauses.Select(e => e.Test)
.Aggregate((l, r) => _sqlExpressionFactory.OrElse(l, r));
.Aggregate(_sqlExpressionFactory.OrElse);
}

return discriminatorValues.Count == 1
Expand Down
Loading

0 comments on commit 1cd05c7

Please sign in to comment.