Skip to content

Commit

Permalink
Create a public abstraction for managing seed data
Browse files Browse the repository at this point in the history
Part of #15096 and #15126

To avoid using the state manager directly.
  • Loading branch information
ajcvickers committed Apr 5, 2019
1 parent 7f84067 commit 79a0591
Show file tree
Hide file tree
Showing 17 changed files with 1,443 additions and 1,323 deletions.
77 changes: 40 additions & 37 deletions src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using System.Linq;
using System.Reflection;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Internal;
Expand Down Expand Up @@ -48,8 +47,8 @@ public class MigrationsModelDiffer : IMigrationsModelDiffer

private static readonly Type[] _constraintOperationTypes = { typeof(AddForeignKeyOperation), typeof(CreateIndexOperation) };

private IStateManager _sourceStateManager;
private IStateManager _targetStateManager;
private IModelDataTracker _sourceModelDataTracker;
private IModelDataTracker _targetModelDataTracker;

/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
Expand All @@ -59,18 +58,18 @@ public MigrationsModelDiffer(
[NotNull] IRelationalTypeMappingSource typeMappingSource,
[NotNull] IMigrationsAnnotationProvider migrationsAnnotations,
[NotNull] IChangeDetector changeDetector,
[NotNull] StateManagerDependencies stateManagerDependencies,
[NotNull] IModelDataTrackerFactory modelDataTrackerFactory,
[NotNull] CommandBatchPreparerDependencies commandBatchPreparerDependencies)
{
Check.NotNull(typeMappingSource, nameof(typeMappingSource));
Check.NotNull(migrationsAnnotations, nameof(migrationsAnnotations));
Check.NotNull(stateManagerDependencies, nameof(stateManagerDependencies));
Check.NotNull(modelDataTrackerFactory, nameof(modelDataTrackerFactory));
Check.NotNull(commandBatchPreparerDependencies, nameof(commandBatchPreparerDependencies));

TypeMappingSource = typeMappingSource;
MigrationsAnnotations = migrationsAnnotations;
ChangeDetector = changeDetector;
StateManagerDependencies = stateManagerDependencies;
ModelDataTrackerFactory = modelDataTrackerFactory;
CommandBatchPreparerDependencies = commandBatchPreparerDependencies;
}

Expand All @@ -90,7 +89,7 @@ public MigrationsModelDiffer(
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
protected virtual StateManagerDependencies StateManagerDependencies { get; }
protected virtual IModelDataTrackerFactory ModelDataTrackerFactory { get; }

/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
Expand Down Expand Up @@ -1430,33 +1429,37 @@ protected virtual void TrackData(
{
if (target == null)
{
_targetStateManager = null;
_targetModelDataTracker = null;
return;
}

_targetStateManager = new StateManager(StateManagerDependencies.With(target));
_targetModelDataTracker = ModelDataTrackerFactory.Create(target);

foreach (var targetEntityType in target.GetEntityTypes())
{
foreach (var targetSeed in targetEntityType.GetData())
{
_targetStateManager.CreateEntry(targetSeed, targetEntityType).SetEntityState(EntityState.Added);
_targetModelDataTracker
.CreateEntry(targetSeed, targetEntityType)
.EntityState = EntityState.Added;
}
}

if (source == null)
{
_sourceStateManager = null;
_sourceModelDataTracker = null;
return;
}

_sourceStateManager = new StateManager(StateManagerDependencies.With(source));
_sourceModelDataTracker = ModelDataTrackerFactory.Create(source);

foreach (var sourceEntityType in source.GetEntityTypes())
{
foreach (var sourceSeed in sourceEntityType.GetData())
{
_sourceStateManager.CreateEntry(sourceSeed, sourceEntityType).SetEntityState(EntityState.Added);
_sourceModelDataTracker
.CreateEntry(sourceSeed, sourceEntityType)
.EntityState = EntityState.Added;
}
}
}
Expand All @@ -1474,18 +1477,18 @@ protected virtual void DiffData(
Check.NotNull(target, nameof(target));
Check.NotNull(diffContext, nameof(diffContext));

var targetTableEntryMappingMap = SharedTableEntryMap<List<InternalEntityEntry>>.CreateSharedTableEntryMapFactory(
var targetTableEntryMappingMap = SharedTableEntryMap<List<IUpdateEntry>>.CreateSharedTableEntryMapFactory(
target.EntityTypes,
_targetStateManager,
_targetModelDataTracker,
target.Name,
target.Schema)
((t, s, c) => new List<InternalEntityEntry>());
((t, s, c) => new List<IUpdateEntry>());

foreach (var targetEntityType in target.EntityTypes)
{
foreach (var targetSeed in targetEntityType.GetData())
{
var targetEntry = GetEntry(targetSeed, targetEntityType, _targetStateManager);
var targetEntry = GetEntry(targetSeed, targetEntityType, _targetModelDataTracker);
var targetEntries = targetTableEntryMappingMap.GetOrAddValue(targetEntry);
targetEntries.Add(targetEntry);
}
Expand Down Expand Up @@ -1536,7 +1539,7 @@ protected virtual void DiffData(

var sourceTableEntryMappingMap = SharedTableEntryMap<EntryMapping>.CreateSharedTableEntryMapFactory(
source.EntityTypes,
_sourceStateManager,
_sourceModelDataTracker,
source.Name,
source.Schema)
((t, s, c) => new EntryMapping());
Expand All @@ -1545,7 +1548,7 @@ protected virtual void DiffData(
{
foreach (var sourceSeed in sourceEntityType.GetData())
{
var sourceEntry = GetEntry(sourceSeed, sourceEntityType, _sourceStateManager);
var sourceEntry = GetEntry(sourceSeed, sourceEntityType, _sourceModelDataTracker);
var entryMapping = sourceTableEntryMappingMap.GetOrAddValue(sourceEntry);
entryMapping.SourceEntries.Add(sourceEntry);

Expand Down Expand Up @@ -1584,7 +1587,7 @@ protected virtual void DiffData(
}
}

var entry = _targetStateManager.TryGetEntry(targetKey, targetKeyValues);
var entry = _targetModelDataTracker.TryGetEntry(targetKey, targetKeyValues);
if (entry == null)
{
continue;
Expand All @@ -1605,7 +1608,7 @@ protected virtual void DiffData(
}
}

targetEntry.SetEntityState(EntityState.Unchanged);
targetEntry.EntityState = EntityState.Unchanged;
}

if (entryMapping.RecreateRow)
Expand Down Expand Up @@ -1687,26 +1690,26 @@ var modelValuesChanged
{
foreach (var targetEntry in entryMapping.TargetEntries)
{
targetEntry.SetEntityState(EntityState.Added);
targetEntry.EntityState = EntityState.Added;
}

foreach (var sourceEntry in entryMapping.SourceEntries)
{
sourceEntry.SetEntityState(EntityState.Deleted);
sourceEntry.EntityState = EntityState.Deleted;
}
}
else
{
foreach (var sourceEntry in entryMapping.SourceEntries)
{
sourceEntry.SetEntityState(EntityState.Detached);
sourceEntry.EntityState = EntityState.Detached;
}
}
}
}

private static InternalEntityEntry GetEntry(
IDictionary<string, object> sourceSeed, IEntityType sourceEntityType, IStateManager stateManager)
private static IUpdateEntry GetEntry(
IDictionary<string, object> sourceSeed, IEntityType sourceEntityType, IModelDataTracker modelDataTracker)
{
var key = sourceEntityType.FindPrimaryKey();
var keyValues = new object[key.Properties.Count];
Expand All @@ -1715,7 +1718,7 @@ private static InternalEntityEntry GetEntry(
keyValues[i] = sourceSeed[key.Properties[i].Name];
}

return stateManager.TryGetEntry(key, keyValues);
return modelDataTracker.TryGetEntry(key, keyValues);
}

/// <summary>
Expand All @@ -1724,30 +1727,30 @@ private static InternalEntityEntry GetEntry(
/// </summary>
protected virtual IEnumerable<MigrationOperation> GetDataOperations()
{
if (_sourceStateManager != null)
if (_sourceModelDataTracker != null)
{
foreach (var sourceEntry in _sourceStateManager.ToListForState(added: true))
foreach (var sourceEntry in _sourceModelDataTracker.Entries.Where(e => e.EntityState == EntityState.Added).ToList())
{
sourceEntry.SetEntityState(EntityState.Detached);
sourceEntry.EntityState = EntityState.Detached;
}
}

foreach (var stateManager in new[] { _sourceStateManager, _targetStateManager })
foreach (var modelDataTracker in new[] { _sourceModelDataTracker, _targetModelDataTracker })
{
if (stateManager == null)
if (modelDataTracker == null)
{
continue;
}

ChangeDetector.DetectChanges(stateManager);
var entries = stateManager.GetEntriesToSave();
modelDataTracker.DetectChanges();
var entries = modelDataTracker.GetEntriesToSave();
if (entries == null
|| entries.Count == 0)
{
continue;
}

var commandBatches = new CommandBatchPreparer(CommandBatchPreparerDependencies.With(() => stateManager))
var commandBatches = new CommandBatchPreparer(CommandBatchPreparerDependencies.With(() => modelDataTracker))
.BatchCommands(entries);

foreach (var commandBatch in commandBatches)
Expand Down Expand Up @@ -2005,8 +2008,8 @@ private static ReferentialAction ToReferentialAction(DeleteBehavior deleteBehavi

private class EntryMapping
{
public HashSet<InternalEntityEntry> SourceEntries { get; } = new HashSet<InternalEntityEntry>();
public HashSet<InternalEntityEntry> TargetEntries { get; } = new HashSet<InternalEntityEntry>();
public HashSet<IUpdateEntry> SourceEntries { get; } = new HashSet<IUpdateEntry>();
public HashSet<IUpdateEntry> TargetEntries { get; } = new HashSet<IUpdateEntry>();
public bool RecreateRow { get; set; }
}

Expand Down
8 changes: 4 additions & 4 deletions src/EFCore.Relational/Update/Internal/CommandBatchPreparer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public class CommandBatchPreparer : ICommandBatchPreparer
private readonly IComparer<ModificationCommand> _modificationCommandComparer;
private readonly IKeyValueIndexFactorySource _keyValueIndexFactorySource;
private readonly int _minBatchSize;
private IStateManager _stateManager;
private IModelDataTracker _modelDataTracker;
private readonly bool _sensitiveLoggingEnabled;

private IReadOnlyDictionary<(string Schema, string Name), SharedTableEntryMapFactory<ModificationCommand>> _sharedTableEntryMapFactories;
Expand All @@ -63,7 +63,7 @@ public CommandBatchPreparer([NotNull] CommandBatchPreparerDependencies dependenc

private CommandBatchPreparerDependencies Dependencies { get; }

private IStateManager StateManager => _stateManager ?? (_stateManager = Dependencies.StateManager());
private IModelDataTracker ModelDataTracker => _modelDataTracker ?? (_modelDataTracker = Dependencies.ModelDataTracker());

/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
Expand Down Expand Up @@ -155,7 +155,7 @@ protected virtual IEnumerable<ModificationCommand> CreateModificationCommands(
if (_sharedTableEntryMapFactories == null)
{
_sharedTableEntryMapFactories = SharedTableEntryMap<ModificationCommand>
.CreateSharedTableEntryMapFactories(entries[0].EntityType.Model, StateManager);
.CreateSharedTableEntryMapFactories(entries[0].EntityType.Model, ModelDataTracker);
}

Dictionary<(string Schema, string Name), SharedTableEntryMap<ModificationCommand>> sharedTablesCommandsMap =
Expand Down Expand Up @@ -300,7 +300,7 @@ private void AddUnchangedSharingEntries(
continue;
}

entry.SetEntityState(EntityState.Modified, modifyProperties: false);
entry.EntityState = EntityState.Modified;

command.AddEntry(entry);
entries.Add(entry);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
Expand Down Expand Up @@ -59,7 +58,7 @@ public CommandBatchPreparerDependencies(
[NotNull] IParameterNameGeneratorFactory parameterNameGeneratorFactory,
[NotNull] IComparer<ModificationCommand> modificationCommandComparer,
[NotNull] IKeyValueIndexFactorySource keyValueIndexFactorySource,
[NotNull] Func<IStateManager> stateManager,
[NotNull] Func<IModelDataTracker> modelDataTracker,
[NotNull] ILoggingOptions loggingOptions,
[NotNull] IDiagnosticsLogger<DbLoggerCategory.Update> updateLogger,
[NotNull] IDbContextOptions options)
Expand All @@ -68,7 +67,7 @@ public CommandBatchPreparerDependencies(
ParameterNameGeneratorFactory = parameterNameGeneratorFactory;
ModificationCommandComparer = modificationCommandComparer;
KeyValueIndexFactorySource = keyValueIndexFactorySource;
StateManager = stateManager;
ModelDataTracker = modelDataTracker;
LoggingOptions = loggingOptions;
UpdateLogger = updateLogger;
Options = options;
Expand Down Expand Up @@ -102,7 +101,7 @@ public CommandBatchPreparerDependencies(
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public Func<IStateManager> StateManager { get; }
public Func<IModelDataTracker> ModelDataTracker { get; }

/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
Expand Down Expand Up @@ -133,7 +132,7 @@ public CommandBatchPreparerDependencies With([NotNull] IModificationCommandBatch
ParameterNameGeneratorFactory,
ModificationCommandComparer,
KeyValueIndexFactorySource,
StateManager,
ModelDataTracker,
LoggingOptions,
UpdateLogger,
Options);
Expand All @@ -149,7 +148,7 @@ public CommandBatchPreparerDependencies With([NotNull] IParameterNameGeneratorFa
parameterNameGeneratorFactory,
ModificationCommandComparer,
KeyValueIndexFactorySource,
StateManager,
ModelDataTracker,
LoggingOptions,
UpdateLogger,
Options);
Expand All @@ -165,7 +164,7 @@ public CommandBatchPreparerDependencies With([NotNull] IComparer<ModificationCom
ParameterNameGeneratorFactory,
modificationCommandComparer,
KeyValueIndexFactorySource,
StateManager,
ModelDataTracker,
LoggingOptions,
UpdateLogger,
Options);
Expand All @@ -181,23 +180,23 @@ public CommandBatchPreparerDependencies With([NotNull] IKeyValueIndexFactorySour
ParameterNameGeneratorFactory,
ModificationCommandComparer,
keyValueIndexFactorySource,
StateManager,
ModelDataTracker,
LoggingOptions,
UpdateLogger,
Options);

/// <summary>
/// Clones this dependency parameter object with one service replaced.
/// </summary>
/// <param name="stateManager"> A replacement for the current dependency of this type. </param>
/// <param name="modelDataTracker"> A replacement for the current dependency of this type. </param>
/// <returns> A new parameter object with the given service replaced. </returns>
public CommandBatchPreparerDependencies With([NotNull] Func<IStateManager> stateManager)
public CommandBatchPreparerDependencies With([NotNull] Func<IModelDataTracker> modelDataTracker)
=> new CommandBatchPreparerDependencies(
ModificationCommandBatchFactory,
ParameterNameGeneratorFactory,
ModificationCommandComparer,
KeyValueIndexFactorySource,
stateManager,
modelDataTracker,
LoggingOptions,
UpdateLogger,
Options);
Expand All @@ -213,7 +212,7 @@ public CommandBatchPreparerDependencies With([NotNull] ILoggingOptions loggingOp
ParameterNameGeneratorFactory,
ModificationCommandComparer,
KeyValueIndexFactorySource,
StateManager,
ModelDataTracker,
loggingOptions,
UpdateLogger,
Options);
Expand All @@ -229,7 +228,7 @@ public CommandBatchPreparerDependencies With([NotNull] IDiagnosticsLogger<DbLogg
ParameterNameGeneratorFactory,
ModificationCommandComparer,
KeyValueIndexFactorySource,
StateManager,
ModelDataTracker,
LoggingOptions,
updateLogger,
Options);
Expand All @@ -245,7 +244,7 @@ public CommandBatchPreparerDependencies With([NotNull] IDbContextOptions options
ParameterNameGeneratorFactory,
ModificationCommandComparer,
KeyValueIndexFactorySource,
StateManager,
ModelDataTracker,
LoggingOptions,
UpdateLogger,
options);
Expand Down
Loading

0 comments on commit 79a0591

Please sign in to comment.