Skip to content

Commit

Permalink
Add a convention that builds a slim model to be used at runtime
Browse files Browse the repository at this point in the history
Allow the design-time model to be accessed when necessary

Fixes #8258
  • Loading branch information
AndriySvyryd committed Mar 23, 2021
1 parent 26c0d2a commit c6fd7ce
Show file tree
Hide file tree
Showing 76 changed files with 1,437 additions and 170 deletions.
2 changes: 1 addition & 1 deletion EFCore.Runtime.slnf
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"test\\EFCore.SqlServer.Tests\\EFCore.SqlServer.Tests.csproj",
"test\\EFCore.Sqlite.FunctionalTests\\EFCore.Sqlite.FunctionalTests.csproj",
"test\\EFCore.Sqlite.Tests\\EFCore.Sqlite.Tests.csproj",
"test\\EFCore.Tests\\EFCore.Tests.csproj",
"test\\EFCore.Tests\\EFCore.Tests.csproj"
]
}
}
15 changes: 9 additions & 6 deletions src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseCreator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.Cosmos.Internal;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Update;
Expand All @@ -20,7 +21,7 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal
public class CosmosDatabaseCreator : IDatabaseCreator
{
private readonly ICosmosClientWrapper _cosmosClient;
private readonly IModel _model;
private readonly IModel _designModel;
private readonly IUpdateAdapterFactory _updateAdapterFactory;
private readonly IDatabase _database;

Expand All @@ -32,12 +33,12 @@ public class CosmosDatabaseCreator : IDatabaseCreator
/// </summary>
public CosmosDatabaseCreator(
ICosmosClientWrapper cosmosClient,
IModel model,
ICurrentDbContext context,
IUpdateAdapterFactory updateAdapterFactory,
IDatabase database)
{
_cosmosClient = cosmosClient;
_model = model;
_designModel = context.Context.DesignTimeModel;
_updateAdapterFactory = updateAdapterFactory;
_database = database;
}
Expand All @@ -51,7 +52,7 @@ public CosmosDatabaseCreator(
public virtual bool EnsureCreated()
{
var created = _cosmosClient.CreateDatabaseIfNotExists();
foreach (var entityType in _model.GetEntityTypes())
foreach (var entityType in _designModel.GetEntityTypes())
{
var containerName = entityType.GetContainer();
if (containerName != null)
Expand Down Expand Up @@ -80,7 +81,7 @@ public virtual async Task<bool> EnsureCreatedAsync(CancellationToken cancellatio
{
var created = await _cosmosClient.CreateDatabaseIfNotExistsAsync(cancellationToken)
.ConfigureAwait(false);
foreach (var entityType in _model.GetEntityTypes())
foreach (var entityType in _designModel.GetEntityTypes())
{
var containerName = entityType.GetContainer();
if (containerName != null)
Expand Down Expand Up @@ -130,10 +131,12 @@ public virtual Task SeedAsync(CancellationToken cancellationToken = default)
private IUpdateAdapter AddSeedData()
{
var updateAdapter = _updateAdapterFactory.CreateStandalone();
foreach (var entityType in _model.GetEntityTypes())
foreach (var entityType in _designModel.GetEntityTypes())
{
IEntityType? targetEntityType = null;
foreach (var targetSeed in entityType.GetSeedData())
{
targetEntityType ??= updateAdapter.Model.FindEntityType(entityType.Name)!;
var entry = updateAdapter.CreateEntry(targetSeed, entityType);
entry.EntityState = EntityState.Added;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public static IServiceCollection AddDbContextDesignTimeServices(
.AddTransient(_ => context.GetService<IMigrationsModelDiffer>())
.AddTransient(_ => context.GetService<IMigrator>())
.AddTransient(_ => context.GetService<IRelationalTypeMappingSource>())
.AddTransient(_ => context.GetService<IModel>())
.AddTransient(_ => context.DesignTimeModel)
.AddTransient(_ => context.GetService<IModelRuntimeInitializer>());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public SnapshotModelProcessor(
model = mutableModel.FinalizeModel();
}

return _modelRuntimeInitializer.Initialize((IModel)model, validationLogger: null);
return _modelRuntimeInitializer.Initialize((IModel)model, designTime: true, validationLogger: null);
}

private void ProcessCollection(IEnumerable<IReadOnlyAnnotatable> metadata, string version)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public virtual IModel Create(DatabaseModel databaseModel, ModelReverseEngineerOp

VisitDatabaseModel(modelBuilder, databaseModel);

return _modelRuntimeInitializer.Initialize(modelBuilder.FinalizeModel(), null);
return _modelRuntimeInitializer.Initialize(modelBuilder.FinalizeModel(), designTime: true, null);
}

/// <summary>
Expand Down
1 change: 1 addition & 0 deletions src/EFCore.InMemory/Storage/Internal/IInMemoryStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public interface IInMemoryStore
/// </summary>
bool EnsureCreated(
IUpdateAdapterFactory updateAdapterFactory,
IModel designModel,
IDiagnosticsLogger<DbLoggerCategory.Update> updateLogger);

/// <summary>
Expand Down
7 changes: 6 additions & 1 deletion src/EFCore.InMemory/Storage/Internal/InMemoryDatabase.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Update;
using Microsoft.EntityFrameworkCore.Utilities;
Expand All @@ -32,6 +34,7 @@ public class InMemoryDatabase : Database, IInMemoryDatabase
private readonly IInMemoryStore _store;
private readonly IUpdateAdapterFactory _updateAdapterFactory;
private readonly IDiagnosticsLogger<DbLoggerCategory.Update> _updateLogger;
private readonly Func<IModel> _getDesignModel;

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand All @@ -43,6 +46,7 @@ public InMemoryDatabase(
DatabaseDependencies dependencies,
IInMemoryStoreCache storeCache,
IDbContextOptions options,
ICurrentDbContext context,
IUpdateAdapterFactory updateAdapterFactory,
IDiagnosticsLogger<DbLoggerCategory.Update> updateLogger)
: base(dependencies)
Expand All @@ -53,6 +57,7 @@ public InMemoryDatabase(
Check.NotNull(updateLogger, nameof(updateLogger));

_store = storeCache.GetStore(options);
_getDesignModel = () => context.Context.DesignTimeModel;
_updateAdapterFactory = updateAdapterFactory;
_updateLogger = updateLogger;
}
Expand Down Expand Up @@ -93,6 +98,6 @@ public override Task<int> SaveChangesAsync(
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual bool EnsureDatabaseCreated()
=> _store.EnsureCreated(_updateAdapterFactory, _updateLogger);
=> _store.EnsureCreated(_updateAdapterFactory, _getDesignModel(), _updateLogger);
}
}
7 changes: 5 additions & 2 deletions src/EFCore.InMemory/Storage/Internal/InMemoryStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public virtual InMemoryIntegerValueGenerator<TProperty> GetIntegerValueGenerator
/// </summary>
public virtual bool EnsureCreated(
IUpdateAdapterFactory updateAdapterFactory,
IModel designModel,
IDiagnosticsLogger<DbLoggerCategory.Update> updateLogger)
{
lock (_lock)
Expand All @@ -80,11 +81,13 @@ public virtual bool EnsureCreated(

var updateAdapter = updateAdapterFactory.CreateStandalone();
var entries = new List<IUpdateEntry>();
foreach (var entityType in updateAdapter.Model.GetEntityTypes())
foreach (var entityType in designModel.GetEntityTypes())
{
IEntityType? targetEntityType = null;
foreach (var targetSeed in entityType.GetSeedData())
{
var entry = updateAdapter.CreateEntry(targetSeed, entityType);
targetEntityType ??= updateAdapter.Model.FindEntityType(entityType.Name)!;
var entry = updateAdapter.CreateEntry(targetSeed, targetEntityType);
entry.EntityState = EntityState.Added;
entries.Add(entry);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ public override ConventionSet CreateConventionSet()
(QueryFilterRewritingConvention)new RelationalQueryFilterRewritingConvention(
Dependencies, RelationalDependencies));

ReplaceConvention(
conventionSet.ModelFinalizedConventions,
(SlimModelConvention)new RelationalSlimModelConvention(Dependencies, RelationalDependencies));

return conventionSet;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ public RelationalConventionSetBuilderDependencies(IRelationalAnnotationProvider
/// <summary>
/// The relational annotation provider.
/// </summary>
[Obsolete("This is now part of RelationalModelRuntimeInitializerDependencies")]
public IRelationalAnnotationProvider RelationalAnnotationProvider { get; init; }
}
}
Loading

0 comments on commit c6fd7ce

Please sign in to comment.