Skip to content

Commit

Permalink
Add NativeAOT support for Change Tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
AndriySvyryd committed Jul 13, 2023
1 parent bb1fb3c commit a8dab2b
Show file tree
Hide file tree
Showing 21 changed files with 1,008 additions and 178 deletions.
8 changes: 8 additions & 0 deletions All.sln
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
azure-pipelines.yml = azure-pipelines.yml
Directory.Build.props = Directory.Build.props
Directory.Build.targets = Directory.Build.targets
global.json = global.json
tools\Resources.tt = tools\Resources.tt
eng\Versions.props = eng\Versions.props
EndProjectSection
Expand Down Expand Up @@ -125,6 +126,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.Trimming.Tests", "te
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.Templates", "src\EFCore.Templates\EFCore.Templates.csproj", "{1FE385D8-8F8B-4EC9-A1A9-AFCC38B8546C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.NativeAotTests", "test\EFCore.NativeAotTests\EFCore.NativeAotTests.csproj", "{2487950B-403A-482C-8ED3-CCF31E9E677F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.SqlServer.HierarchyId", "src\EFCore.SqlServer.HierarchyId\EFCore.SqlServer.HierarchyId.csproj", "{8F722A02-71A4-4787-ACD8-FB7D5B7AE648}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.SqlServer.HierarchyId.Tests", "test\EFCore.SqlServer.HierarchyId.Tests\EFCore.SqlServer.HierarchyId.Tests.csproj", "{01F86E65-6448-424C-AAB5-9C6427EF6FD4}"
Expand Down Expand Up @@ -339,6 +342,10 @@ Global
{1FE385D8-8F8B-4EC9-A1A9-AFCC38B8546C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1FE385D8-8F8B-4EC9-A1A9-AFCC38B8546C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1FE385D8-8F8B-4EC9-A1A9-AFCC38B8546C}.Release|Any CPU.Build.0 = Release|Any CPU
{2487950B-403A-482C-8ED3-CCF31E9E677F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2487950B-403A-482C-8ED3-CCF31E9E677F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2487950B-403A-482C-8ED3-CCF31E9E677F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2487950B-403A-482C-8ED3-CCF31E9E677F}.Release|Any CPU.Build.0 = Release|Any CPU
{8F722A02-71A4-4787-ACD8-FB7D5B7AE648}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8F722A02-71A4-4787-ACD8-FB7D5B7AE648}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8F722A02-71A4-4787-ACD8-FB7D5B7AE648}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -410,6 +417,7 @@ Global
{F1B2E5A0-8C74-414A-B262-353FEE325E9F} = {258D5057-81B9-40EC-A872-D21E27452749}
{933C8662-817C-4F45-B98B-6557E28F7BB1} = {258D5057-81B9-40EC-A872-D21E27452749}
{1FE385D8-8F8B-4EC9-A1A9-AFCC38B8546C} = {CE6B50B2-34AE-44C9-940A-4E48C3E1B3BC}
{2487950B-403A-482C-8ED3-CCF31E9E677F} = {258D5057-81B9-40EC-A872-D21E27452749}
{8F722A02-71A4-4787-ACD8-FB7D5B7AE648} = {CE6B50B2-34AE-44C9-940A-4E48C3E1B3BC}
{01F86E65-6448-424C-AAB5-9C6427EF6FD4} = {258D5057-81B9-40EC-A872-D21E27452749}
{3D935B7D-80BD-49AD-BDC9-E1B0C9D9494F} = {CE6B50B2-34AE-44C9-940A-4E48C3E1B3BC}
Expand Down
4 changes: 2 additions & 2 deletions eng/common/tools.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -760,9 +760,9 @@ function MSBuild() {
(Join-Path $basePath (Join-Path $buildTool.Framework 'Microsoft.DotNet.ArcadeLogging.dll')),
(Join-Path $basePath (Join-Path $buildTool.Framework 'Microsoft.DotNet.Arcade.Sdk.dll')),
(Join-Path $basePath (Join-Path netcoreapp2.1 'Microsoft.DotNet.ArcadeLogging.dll')),
(Join-Path $basePath (Join-Path netcoreapp2.1 'Microsoft.DotNet.Arcade.Sdk.dll'))
(Join-Path $basePath (Join-Path netcoreapp2.1 'Microsoft.DotNet.Arcade.Sdk.dll')),
(Join-Path $basePath (Join-Path netcoreapp3.1 'Microsoft.DotNet.ArcadeLogging.dll')),
(Join-Path $basePath (Join-Path netcoreapp3.1 'Microsoft.DotNet.Arcade.Sdk.dll'))
(Join-Path $basePath (Join-Path netcoreapp3.1 'Microsoft.DotNet.Arcade.Sdk.dll')),
(Join-Path $basePath (Join-Path net7.0 'Microsoft.DotNet.ArcadeLogging.dll')),
(Join-Path $basePath (Join-Path net7.0 'Microsoft.DotNet.Arcade.Sdk.dll'))
)
Expand Down
59 changes: 37 additions & 22 deletions src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata.Internal;

Expand Down Expand Up @@ -185,26 +184,22 @@ public async Task SetEntityStateAsync(
CancellationToken cancellationToken = default)
{
var oldState = _stateData.EntityState;
var adding = false;
await SetupAsync().ConfigureAwait(false);
bool adding = PrepareForAdd(entityState);
entityState = await PropagateToUnknownKeyAsync(
oldState, entityState, adding, forceStateWhenUnknownKey, cancellationToken).ConfigureAwait(false);

if ((adding || oldState is EntityState.Detached)
&& await StateManager.ValueGenerationManager
.GenerateAsync(this, includePrimaryKey: adding, cancellationToken).ConfigureAwait(false)
&& fallbackState.HasValue)
{
entityState = fallbackState.Value;
await SetupAsync().ConfigureAwait(false);
}

SetEntityState(oldState, entityState, acceptChanges, modifyProperties);

async Task SetupAsync()
{
adding = PrepareForAdd(entityState);
entityState = await PropagateToUnknownKeyAsync(
oldState, entityState, adding, forceStateWhenUnknownKey, cancellationToken).ConfigureAwait(false);
}

SetEntityState(oldState, entityState, acceptChanges, modifyProperties);
}

private EntityState PropagateToUnknownKey(
Expand Down Expand Up @@ -829,8 +824,13 @@ private static readonly MethodInfo ReadOriginalValueMethod
internal static MethodInfo MakeReadOriginalValueMethod(Type type)
=> ReadOriginalValueMethod.MakeGenericMethod(type);

[UsedImplicitly]
private T ReadOriginalValue<T>(IProperty property, int originalValueIndex)
/// <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 T ReadOriginalValue<T>(IProperty property, int originalValueIndex)
=> _originalValues.GetValue<T>(this, property, originalValueIndex);

private static readonly MethodInfo ReadRelationshipSnapshotValueMethod
Expand All @@ -842,8 +842,13 @@ private static readonly MethodInfo ReadRelationshipSnapshotValueMethod
internal static MethodInfo MakeReadRelationshipSnapshotValueMethod(Type type)
=> ReadRelationshipSnapshotValueMethod.MakeGenericMethod(type);

[UsedImplicitly]
private T ReadRelationshipSnapshotValue<T>(IPropertyBase propertyBase, int relationshipSnapshotIndex)
/// <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 T ReadRelationshipSnapshotValue<T>(IPropertyBase propertyBase, int relationshipSnapshotIndex)
=> _relationshipsSnapshot.GetValue<T>(this, propertyBase, relationshipSnapshotIndex);

[UnconditionalSuppressMessage(
Expand All @@ -855,21 +860,31 @@ internal static MethodInfo MakeReadStoreGeneratedValueMethod(Type type)
private static readonly MethodInfo ReadStoreGeneratedValueMethod
= typeof(InternalEntityEntry).GetTypeInfo().GetDeclaredMethod(nameof(ReadStoreGeneratedValue))!;

[UsedImplicitly]
private T ReadStoreGeneratedValue<T>(int storeGeneratedIndex)
/// <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 T ReadStoreGeneratedValue<T>(int storeGeneratedIndex)
=> _storeGeneratedValues.GetValue<T>(storeGeneratedIndex);

private static readonly MethodInfo ReadTemporaryValueMethod
= typeof(InternalEntityEntry).GetTypeInfo().GetDeclaredMethod(nameof(ReadTemporaryValue))!;
= typeof(InternalEntityEntry).GetMethod(nameof(ReadTemporaryValue))!;

[UnconditionalSuppressMessage(
"ReflectionAnalysis", "IL2060",
Justification = "MakeGenericMethod wrapper, see https://github.com/dotnet/linker/issues/2482")]
internal static MethodInfo MakeReadTemporaryValueMethod(Type type)
=> ReadTemporaryValueMethod.MakeGenericMethod(type);

[UsedImplicitly]
private T ReadTemporaryValue<T>(int storeGeneratedIndex)
/// <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 T ReadTemporaryValue<T>(int storeGeneratedIndex)
=> _temporaryValues.GetValue<T>(storeGeneratedIndex);

private static readonly MethodInfo GetCurrentValueMethod
Expand Down Expand Up @@ -942,7 +957,7 @@ private void WritePropertyValue(

var setter = forMaterialization
? concretePropertyBase.MaterializationSetter
: concretePropertyBase.Setter;
: concretePropertyBase.GetSetter();

setter.SetClrValue(Entity, value);
}
Expand Down Expand Up @@ -1124,7 +1139,7 @@ public void EnsureTemporaryValues()
{
if (_temporaryValues.IsEmpty)
{
_temporaryValues = new SidecarValues(((IRuntimeEntityType)EntityType).TemporaryValuesFactory(this));
_temporaryValues = new SidecarValues(EntityType.TemporaryValuesFactory(this));
}
}

Expand All @@ -1138,7 +1153,7 @@ public void EnsureStoreGeneratedValues()
{
if (_storeGeneratedValues.IsEmpty)
{
_storeGeneratedValues = new SidecarValues(((IRuntimeEntityType)EntityType).StoreGeneratedValuesFactory());
_storeGeneratedValues = new SidecarValues(EntityType.StoreGeneratedValuesFactory());
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/EFCore/ChangeTracking/Internal/SidecarValues.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ private readonly struct SidecarValues
{
private readonly ISnapshot _values;

public SidecarValues(ISnapshot valuesFactory)
public SidecarValues(ISnapshot values)
{
_values = valuesFactory;
_values = values;
}

public bool TryGetValue(int index, out object? value)
Expand Down
Loading

0 comments on commit a8dab2b

Please sign in to comment.