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

[5.0-rc2] Also clear the store generated values when setting a normal value #22607

Merged
merged 2 commits into from
Sep 19, 2020
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
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ private readonly IDictionary<Expression, ParameterExpression> _projectionBinding
private readonly IDictionary<Expression, (IEntityType EntityType, Expression JObjectExpression)> _ownerMappings
= new Dictionary<Expression, (IEntityType, Expression)>();

private readonly IDictionary<Expression, ParameterExpression> _ordinalParameterBindings
= new Dictionary<Expression, ParameterExpression>();
private readonly IDictionary<Expression, Expression> _ordinalParameterBindings
= new Dictionary<Expression, Expression>();

private List<IncludeExpression> _pendingIncludes
= new List<IncludeExpression>();
Expand Down Expand Up @@ -269,9 +269,10 @@ protected override Expression VisitExtension(Expression extensionExpression)

var accessExpression = objectArrayProjection.InnerProjection.AccessExpression;
_projectionBindings[accessExpression] = jObjectParameter;
_ownerMappings[accessExpression] = (
objectArrayProjection.Navigation.DeclaringEntityType, objectArrayProjection.AccessExpression);
_ordinalParameterBindings[accessExpression] = ordinalParameter;
_ownerMappings[accessExpression] =
(objectArrayProjection.Navigation.DeclaringEntityType, objectArrayProjection.AccessExpression);
_ordinalParameterBindings[accessExpression] = Expression.Add(
ordinalParameter, Expression.Constant(1, typeof(int)));

var innerShaper = (BlockExpression)Visit(collectionShaperExpression.InnerShaper);

Expand Down
6 changes: 3 additions & 3 deletions src/EFCore.Cosmos/Update/Internal/DocumentSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public virtual JObject CreateDocument([NotNull] IUpdateEntry entry, int? ordinal
}
else
{
var embeddedOrdinal = 0;
var embeddedOrdinal = 1;
var array = new JArray();
foreach (var dependent in (IEnumerable)embeddedValue)
{
Expand Down Expand Up @@ -227,7 +227,7 @@ public virtual JObject UpdateDocument([NotNull] JObject document, [NotNull] IUpd
}
else
{
var embeddedOrdinal = 0;
var embeddedOrdinal = 1;
var ordinalKeyProperty = GetOrdinalKeyProperty(fk.DeclaringEntityType);
if (ordinalKeyProperty != null)
{
Expand Down Expand Up @@ -273,7 +273,7 @@ public virtual JObject UpdateDocument([NotNull] JObject document, [NotNull] IUpd
}
}

embeddedOrdinal = 0;
embeddedOrdinal = 1;
var array = new JArray();
foreach (var dependent in (IEnumerable)embeddedValue)
{
Expand Down
51 changes: 25 additions & 26 deletions src/EFCore/ChangeTracking/Internal/ChangeDetector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,7 @@ public virtual void PropertyChanged(InternalEntityEntry entry, IPropertyBase pro
ThrowIfKeyChanged(entry, property);
}

if (property.GetRelationshipIndex() != -1)
{
DetectKeyChange(entry, property);
}
DetectKeyChange(entry, property);
}
else if (propertyBase.GetRelationshipIndex() != -1
&& propertyBase is INavigationBase navigation)
Expand Down Expand Up @@ -274,34 +271,36 @@ private void LogChangeDetected(InternalEntityEntry entry, IProperty property, ob

private void DetectKeyChange(InternalEntityEntry entry, IProperty property)
{
if (property.GetRelationshipIndex() >= 0)
if (property.GetRelationshipIndex() < 0)
{
var snapshotValue = entry.GetRelationshipSnapshotValue(property);
var currentValue = entry[property];
return;
}

var comparer = property.GetKeyValueComparer();
var snapshotValue = entry.GetRelationshipSnapshotValue(property);
var currentValue = entry[property];

// Note that mutation of a byte[] key is not supported or detected, but two different instances
// of byte[] with the same content must be detected as equal.
if (!(comparer?.Equals(currentValue, snapshotValue)
?? StructuralComparisons.StructuralEqualityComparer.Equals(currentValue, snapshotValue)))
{
var keys = property.GetContainingKeys();
var foreignKeys = property.GetContainingForeignKeys()
.Where(fk => fk.DeclaringEntityType.IsAssignableFrom(entry.EntityType));
var comparer = property.GetKeyValueComparer();

if (_loggingOptions.IsSensitiveDataLoggingEnabled)
{
_logger.ForeignKeyChangeDetectedSensitive(entry, property, snapshotValue, currentValue);
}
else
{
_logger.ForeignKeyChangeDetected(entry, property, snapshotValue, currentValue);
}
// Note that mutation of a byte[] key is not supported or detected, but two different instances
// of byte[] with the same content must be detected as equal.
if (!(comparer?.Equals(currentValue, snapshotValue)
?? StructuralComparisons.StructuralEqualityComparer.Equals(currentValue, snapshotValue)))
{
var keys = property.GetContainingKeys();
var foreignKeys = property.GetContainingForeignKeys()
.Where(fk => fk.DeclaringEntityType.IsAssignableFrom(entry.EntityType));

entry.StateManager.InternalEntityEntryNotifier.KeyPropertyChanged(
entry, property, keys, foreignKeys, snapshotValue, currentValue);
if (_loggingOptions.IsSensitiveDataLoggingEnabled)
{
_logger.ForeignKeyChangeDetectedSensitive(entry, property, snapshotValue, currentValue);
}
else
{
_logger.ForeignKeyChangeDetected(entry, property, snapshotValue, currentValue);
}

entry.StateManager.InternalEntityEntryNotifier.KeyPropertyChanged(
entry, property, keys, foreignKeys, snapshotValue, currentValue);
}
}

Expand Down
29 changes: 21 additions & 8 deletions src/EFCore/ChangeTracking/Internal/InternalEntityEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1045,8 +1045,6 @@ public object this[[NotNull] IPropertyBase propertyBase] // Intentionally non-vi
{
get
{
var value = ReadPropertyValue(propertyBase);

var storeGeneratedIndex = propertyBase.GetStoreGeneratedIndex();
if (storeGeneratedIndex != -1)
{
Expand All @@ -1062,6 +1060,7 @@ public object this[[NotNull] IPropertyBase propertyBase] // Intentionally non-vi
return generatedValue;
}

var value = ReadPropertyValue(propertyBase);
if (equals(value, defaultValue))
{
if (_temporaryValues.TryGetValue(storeGeneratedIndex, out generatedValue)
Expand All @@ -1070,9 +1069,11 @@ public object this[[NotNull] IPropertyBase propertyBase] // Intentionally non-vi
return generatedValue;
}
}

return value;
}

return value;
return ReadPropertyValue(propertyBase);
}

[param: CanBeNull] set => SetProperty(propertyBase, value, isMaterialization: false);
Expand Down Expand Up @@ -1178,12 +1179,24 @@ private void SetProperty(
{
WritePropertyValue(propertyBase, value, isMaterialization);

if (currentValueType != CurrentValueType.Normal
&& !_temporaryValues.IsEmpty)
switch (currentValueType)
{
var defaultValue = asProperty.ClrType.GetDefaultValue();
var storeGeneratedIndex = asProperty.GetStoreGeneratedIndex();
_temporaryValues.SetValue(asProperty, defaultValue, storeGeneratedIndex);
case CurrentValueType.StoreGenerated:
if (!_storeGeneratedValues.IsEmpty)
{
var defaultValue = asProperty.ClrType.GetDefaultValue();
var storeGeneratedIndex = asProperty.GetStoreGeneratedIndex();
_storeGeneratedValues.SetValue(asProperty, defaultValue, storeGeneratedIndex);
}
break;
case CurrentValueType.Temporary:
if (!_temporaryValues.IsEmpty)
smitpatel marked this conversation as resolved.
Show resolved Hide resolved
{
var defaultValue = asProperty.ClrType.GetDefaultValue();
var storeGeneratedIndex = asProperty.GetStoreGeneratedIndex();
_temporaryValues.SetValue(asProperty, defaultValue, storeGeneratedIndex);
}
break;
}
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@ public virtual void Table_can_configure_TPT_with_Owned()
var dogType = model.FindEntityType(typeof(Dog));
Assert.Equal("Dogs", dogType.GetTableMappings().Last().Table.Name);
context.Set<Cat>().Add(
new Cat { Key = 1, Species = "Felis catus", Tag = new PetTag { TagId = 2 } });
var petFood = new PetFood() { FoodName = "Fish" };
context.Add(petFood);
context.Add(
new Cat { Species = "Felis catus", Tag = new PetTag { TagId = 2 }, FavoritePetFood = petFood });
context.SaveChanges();
},
Expand All @@ -66,10 +69,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con
{
base.OnModelCreating(modelBuilder, context);

modelBuilder.Entity<Animal>().ToTable("Animals").Property(x => x.Key).ValueGeneratedNever();
modelBuilder.Entity<Pet>().ToTable("Pets").HasOne(x => x.CatFriend);
modelBuilder.Entity<Cat>().ToTable("Cats");
modelBuilder.Entity<Dog>().ToTable("Dogs");
modelBuilder.Entity<Animal>();
modelBuilder.Entity<Pet>();
modelBuilder.Entity<Cat>();
modelBuilder.Entity<Dog>();
}
}

Expand All @@ -86,10 +89,10 @@ protected class Pet : Animal
{
public string Name { get; set; }

[Column("CatFriend_Id")]
[ForeignKey(nameof(CatFriend))]
public int? CatFriendId { get; set; }
public Cat CatFriend { get; set; }
[Column("FavoritePetFood_Id")]
[ForeignKey(nameof(FavoritePetFood))]
public int? FavoritePetFoodId { get; set; }
public PetFood FavoritePetFood { get; set; }

[Required]
public PetTag Tag { get; set; }
Expand All @@ -113,5 +116,15 @@ protected sealed class PetTag
[Required]
public uint? TagId { get; set; }
}

[Table("PetFoods")]
public sealed class PetFood
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("PetFoods_Id")]
public int PetFoodId { get; set; }

public string FoodName { get; set; }
}
}
}