Skip to content

Commit

Permalink
Replace shadow entities with property bag entity types. (#23748)
Browse files Browse the repository at this point in the history
Fixes #21294
  • Loading branch information
AndriySvyryd committed Dec 22, 2020
1 parent b90e28e commit 68d54dd
Show file tree
Hide file tree
Showing 51 changed files with 241 additions and 562 deletions.
2 changes: 1 addition & 1 deletion EFCore.Runtime.slnf
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"test\\EFCore.AspNet.Specification.Tests\\EFCore.AspNet.Specification.Tests.csproj",
"test\\EFCore.AspNet.SqlServer.FunctionalTests\\EFCore.AspNet.SqlServer.FunctionalTests.csproj",
"test\\EFCore.AspNet.Sqlite.FunctionalTests\\EFCore.AspNet.Sqlite.FunctionalTests.csproj",
"test\\EFCore.AspNet.InMemory.FunctionalTests\\EFCore.AspNet.InMemory.FunctionalTests.csproj"
"test\\EFCore.AspNet.InMemory.FunctionalTests\\EFCore.AspNet.InMemory.FunctionalTests.csproj",
"test\\EFCore.Cosmos.FunctionalTests\\EFCore.Cosmos.FunctionalTests.csproj",
"test\\EFCore.Cosmos.Tests\\EFCore.Cosmos.Tests.csproj",
"test\\EFCore.CrossStore.FunctionalTests\\EFCore.CrossStore.FunctionalTests.csproj",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -696,13 +696,13 @@ private void GenerateRelationship(IForeignKey foreignKey, bool useDataAnnotation
canUseDataAnnotations = false;
lines.Add(
$".{nameof(ReferenceReferenceBuilder.HasPrincipalKey)}"
+ (foreignKey.IsUnique ? $"<{foreignKey.PrincipalEntityType.DisplayName()}>" : "")
+ (foreignKey.IsUnique ? $"<{foreignKey.PrincipalEntityType.Name}>" : "")
+ $"({_code.Lambda(foreignKey.PrincipalKey.Properties, "p")})");
}

lines.Add(
$".{nameof(ReferenceReferenceBuilder.HasForeignKey)}"
+ (foreignKey.IsUnique ? $"<{foreignKey.DeclaringEntityType.DisplayName()}>" : "")
+ (foreignKey.IsUnique ? $"<{foreignKey.DeclaringEntityType.Name}>" : "")
+ $"({_code.Lambda(foreignKey.Properties, "d")})");

var defaultOnDeleteAction = foreignKey.IsRequired
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Utilities;

namespace Microsoft.EntityFrameworkCore.Scaffolding.Internal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public override ScaffoldedModel GenerateModel(
generatedCode = CSharpEntityTypeGenerator.WriteCode(entityType, options.ModelNamespace, options.UseDataAnnotations);

// output EntityType poco .cs file
var entityTypeFileName = entityType.DisplayName() + FileExtension;
var entityTypeFileName = entityType.Name + FileExtension;
resultingFiles.AdditionalFiles.Add(
new ScaffoldedFile { Path = entityTypeFileName, Code = generatedCode });
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,7 @@ protected virtual IMutableForeignKey VisitForeignKey([NotNull] ModelBuilder mode
DesignStrings.ForeignKeyScaffoldErrorPrincipalKeyNotFound(
foreignKey.DisplayName(),
string.Join(CultureInfo.CurrentCulture.TextInfo.ListSeparator, principalColumns),
principalEntityType.DisplayName()));
principalEntityType.Name));

return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1662,9 +1662,13 @@ protected virtual void TrackData(
{
foreach (var targetSeed in targetEntityType.GetSeedData())
{
_targetUpdateAdapter
.CreateEntry(targetSeed, targetEntityType)
.EntityState = EntityState.Added;
var targetEntry = _targetUpdateAdapter.CreateEntry(targetSeed, targetEntityType);
if (targetEntry.ToEntityEntry().Entity is Dictionary<string, object> targetBag)
{
targetBag.Remove((key, _, target) => !target.ContainsKey(key), targetSeed);
}

targetEntry.EntityState = EntityState.Added;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,7 @@ public virtual int Compare(ModificationCommand x, ModificationCommand y)
return result;
}

if (xState != EntityState.Added
&& x.Entries.Count > 0
if (x.Entries.Count > 0
&& y.Entries.Count > 0)
{
var xEntry = x.Entries[0];
Expand All @@ -83,15 +82,18 @@ public virtual int Compare(ModificationCommand x, ModificationCommand y)
}
}

var xKey = xEntry.EntityType.FindPrimaryKey();
for (var i = 0; i < xKey.Properties.Count; i++)
if (xState != EntityState.Added)
{
var xKeyProperty = xKey.Properties[i];

result = xKeyProperty.GetCurrentValueComparer().Compare(xEntry, yEntry);
if (result != 0)
var xKey = xEntry.EntityType.FindPrimaryKey();
for (var i = 0; i < xKey.Properties.Count; i++)
{
return result;
var xKeyProperty = xKey.Properties[i];

result = xKeyProperty.GetCurrentValueComparer().Compare(xEntry, yEntry);
if (result != 0)
{
return result;
}
}
}
}
Expand Down
15 changes: 3 additions & 12 deletions src/EFCore/ChangeTracking/Internal/InternalEntityEntryFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@ public virtual InternalEntityEntry Create(

private static InternalEntityEntry NewInternalEntityEntry(IStateManager stateManager, IEntityType entityType, object entity)
{
if (!entityType.HasClrType)
{
return new InternalShadowEntityEntry(stateManager, entityType);
}

Check.DebugAssert(entity != null, "entity is null");

return entityType.ShadowPropertyCount() > 0
Expand All @@ -65,12 +60,8 @@ private static InternalEntityEntry NewInternalEntityEntry(
IEntityType entityType,
object entity,
in ValueBuffer valueBuffer)
{
return !entityType.HasClrType
? new InternalShadowEntityEntry(stateManager, entityType, valueBuffer)
: entityType.ShadowPropertyCount() > 0
? (InternalEntityEntry)new InternalMixedEntityEntry(stateManager, entityType, entity, valueBuffer)
: new InternalClrEntityEntry(stateManager, entityType, entity);
}
=> entityType.ShadowPropertyCount() > 0
? (InternalEntityEntry)new InternalMixedEntityEntry(stateManager, entityType, entity, valueBuffer)
: new InternalClrEntityEntry(stateManager, entityType, entity);
}
}
161 changes: 0 additions & 161 deletions src/EFCore/ChangeTracking/Internal/InternalShadowEntityEntry.cs

This file was deleted.

4 changes: 1 addition & 3 deletions src/EFCore/ChangeTracking/Internal/StateManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -303,9 +303,7 @@ public virtual InternalEntityEntry CreateEntry(IDictionary<string, object> value
}

var valueBuffer = new ValueBuffer(valuesArray);
var entity = entityType.HasClrType
? EntityMaterializerSource.GetMaterializer(entityType)(new MaterializationContext(valueBuffer, Context))
: null;
var entity = EntityMaterializerSource.GetMaterializer(entityType)(new MaterializationContext(valueBuffer, Context));

var shadowPropertyValueBuffer = new ValueBuffer(shadowPropertyValuesArray);
var entry = _internalEntityEntryFactory.Create(this, entityType, entity, shadowPropertyValueBuffer);
Expand Down
5 changes: 0 additions & 5 deletions src/EFCore/Extensions/EntityTypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -330,11 +330,6 @@ public static IEnumerable<IIndex> GetDeclaredIndexes([NotNull] this IEntityType
[DebuggerStepThrough]
public static string DisplayName([NotNull] this ITypeBase type)
{
if (type.ClrType == null)
{
return type.Name;
}

if (!type.HasSharedClrType)
{
return type.ClrType.ShortDisplayName();
Expand Down
19 changes: 6 additions & 13 deletions src/EFCore/Infrastructure/ModelValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ public virtual void Validate(IModel model, IDiagnosticsLogger<DbLoggerCategory.M
{
((Model)model).IsValidated = true;

#pragma warning disable CS0618 // Type or member is obsolete
ValidateNoShadowEntities(model, logger);
#pragma warning restore CS0618 // Type or member is obsolete
ValidateIgnoredMembers(model, logger);
ValidatePropertyMapping(model, logger);
ValidateRelationships(model, logger);
Expand Down Expand Up @@ -162,7 +164,7 @@ protected virtual void ValidatePropertyMapping(
entityType.DisplayName(), unmappedProperty.Name, unmappedProperty.ClrType.ShortDisplayName()));
}

if (!entityType.HasClrType)
if (entityType.ClrType == Model.DefaultPropertyBagType)
{
continue;
}
Expand Down Expand Up @@ -370,18 +372,11 @@ protected virtual void ValidateIgnoredMembers(
/// </summary>
/// <param name="model"> The model to validate. </param>
/// <param name="logger"> The logger to use. </param>
[Obsolete("Shadow entity types cannot be created anymore")]
protected virtual void ValidateNoShadowEntities(
[NotNull] IModel model,
[NotNull] IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)
{
Check.NotNull(model, nameof(model));

var firstShadowEntity = model.GetEntityTypes().FirstOrDefault(entityType => !entityType.HasClrType);
if (firstShadowEntity != null)
{
throw new InvalidOperationException(
CoreStrings.ShadowEntity(firstShadowEntity.DisplayName()));
}
}

/// <summary>
Expand Down Expand Up @@ -745,8 +740,7 @@ protected virtual void ValidateOwnership(
ownership.PrincipalEntityType.DisplayName()));
}
}
else if (entityType.HasClrType
&& ((IMutableModel)model).IsOwned(entityType.ClrType))
else if (((IMutableModel)model).IsOwned(entityType.ClrType))
{
throw new InvalidOperationException(CoreStrings.OwnerlessOwnedType(entityType.DisplayName()));
}
Expand Down Expand Up @@ -1103,8 +1097,7 @@ protected virtual void ValidateData([NotNull] IModel model, [NotNull] IDiagnosti
entityType.DisplayName(), key.Properties.Format()));
}

entry = new InternalShadowEntityEntry(null, entityType);

entry = new InternalClrEntityEntry(null, entityType, seedDatum);
identityMap.Add(keyValues, entry);
}
}
Expand Down
Loading

0 comments on commit 68d54dd

Please sign in to comment.