diff --git a/src/EFCore.Relational/Infrastructure/RelationalModelCustomizer.cs b/src/EFCore.Relational/Infrastructure/RelationalModelCustomizer.cs
index 725bc7b67fc..1767977204b 100644
--- a/src/EFCore.Relational/Infrastructure/RelationalModelCustomizer.cs
+++ b/src/EFCore.Relational/Infrastructure/RelationalModelCustomizer.cs
@@ -1,26 +1,14 @@
// 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.Linq;
-using System.Reflection;
using JetBrains.Annotations;
-using Microsoft.EntityFrameworkCore.Internal;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Utilities;
using Microsoft.Extensions.DependencyInjection;
namespace Microsoft.EntityFrameworkCore.Infrastructure
{
///
///
- /// Builds the model for a given context. This default implementation builds the model by calling
- /// on the context.
- ///
- ///
- /// Also, entity types found as properties on the context are mapped
- /// to tables named for the DbSet property names, and public static methods on the context marked with
- /// are mapped to database functions.
+ /// Builds the model for a given context.
///
///
/// This type is typically used by database providers (and other extensions). It is generally
@@ -42,80 +30,5 @@ public RelationalModelCustomizer([NotNull] ModelCustomizerDependencies dependenc
: base(dependencies)
{
}
-
- ///
- ///
- /// Performs additional configuration of the model in addition to what is discovered by convention. This implementation
- /// builds the model for a given context by calling
- /// on the context.
- ///
- ///
- /// Also, entity types found as properties on the context are mapped
- /// to tables named for the DbSet property names, and public static methods on the context marked with
- /// are mapped to database functions.
- ///
- ///
- ///
- /// The builder being used to construct the model.
- ///
- ///
- /// The context instance that the model is being created for.
- ///
- public override void Customize(ModelBuilder modelBuilder, DbContext context)
- {
- FindDbFunctions(modelBuilder, context);
-
- base.Customize(modelBuilder, context);
- }
-
- ///
- /// Adds to the model function mappings found as public static methods on the context marked with
- /// the .
- ///
- /// The being used to build the model.
- /// The context to find function methods on.
- protected virtual void FindDbFunctions([NotNull] ModelBuilder modelBuilder, [NotNull] DbContext context)
- {
- Check.NotNull(modelBuilder, nameof(modelBuilder));
- Check.NotNull(context, nameof(context));
-
- var contextType = context.GetType();
-
- while (contextType != typeof(DbContext))
- {
- var functions = contextType.GetMethods(
- BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance
- | BindingFlags.Static | BindingFlags.DeclaredOnly)
- .Where(mi => mi.GetCustomAttributes(typeof(DbFunctionAttribute)).Any());
-
- foreach (var function in functions)
- {
- modelBuilder.HasDbFunction(function);
- }
-
- contextType = contextType.BaseType;
- }
- }
-
- ///
- /// Adds the entity types found in properties on the context to the model.
- ///
- /// The being used to build the model.
- /// The context type to find properties on.
- protected override void FindSets(ModelBuilder modelBuilder, Type contextType)
- {
- base.FindSets(modelBuilder, contextType);
-
- var sets = Dependencies.SetFinder.CreateClrTypeDbSetMapping(contextType);
-
- foreach (var entityType in modelBuilder.Model.GetEntityTypes().Cast())
- {
- if (entityType.BaseType == null
- && sets.ContainsKey(entityType.ClrType))
- {
- entityType.Builder.ToTable(sets[entityType.ClrType].Name);
- }
- }
- }
}
}
diff --git a/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs b/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs
index fe311c5fe3c..f0b7ddd88b2 100644
--- a/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs
+++ b/src/EFCore.Relational/Metadata/Conventions/Infrastructure/RelationalConventionSetBuilder.cs
@@ -70,13 +70,21 @@ public override ConventionSet CreateConventionSet()
conventionSet.PropertyAddedConventions.Add(relationalColumnAttributeConvention);
- var storeGenerationConvention = new StoreGenerationConvention(Dependencies, RelationalDependencies);
+ var tableNameFromDbSetConvention = new TableNameFromDbSetConvention(Dependencies, RelationalDependencies);
conventionSet.EntityTypeAddedConventions.Add(new RelationalTableAttributeConvention(Dependencies, RelationalDependencies));
- conventionSet.EntityTypeBaseTypeChangedConventions.Add(new TableNameFromDbSetConvention(Dependencies, RelationalDependencies));
+ conventionSet.EntityTypeAddedConventions.Add(tableNameFromDbSetConvention);
+
+ conventionSet.EntityTypeBaseTypeChangedConventions.Add(tableNameFromDbSetConvention);
+
conventionSet.PropertyFieldChangedConventions.Add(relationalColumnAttributeConvention);
+
+ var storeGenerationConvention = new StoreGenerationConvention(Dependencies, RelationalDependencies);
conventionSet.PropertyAnnotationChangedConventions.Add(storeGenerationConvention);
conventionSet.PropertyAnnotationChangedConventions.Add((RelationalValueGenerationConvention)valueGenerationConvention);
+ var dbFunctionAttributeConvention = new RelationalDbFunctionAttributeConvention(Dependencies, RelationalDependencies);
+ conventionSet.ModelInitializedConventions.Add(dbFunctionAttributeConvention);
+
var sharedTableConvention = new SharedTableConvention(Dependencies, RelationalDependencies);
ConventionSet.AddBefore(
conventionSet.ModelFinalizedConventions,
@@ -87,7 +95,7 @@ public override ConventionSet CreateConventionSet()
sharedTableConvention,
typeof(ValidatingConvention));
- conventionSet.ModelAnnotationChangedConventions.Add(new RelationalDbFunctionConvention(Dependencies, RelationalDependencies));
+ conventionSet.ModelAnnotationChangedConventions.Add(dbFunctionAttributeConvention);
return conventionSet;
}
diff --git a/src/EFCore.Relational/Metadata/Conventions/RelationalDbFunctionConvention.cs b/src/EFCore.Relational/Metadata/Conventions/RelationalDbFunctionAttributeConvention.cs
similarity index 70%
rename from src/EFCore.Relational/Metadata/Conventions/RelationalDbFunctionConvention.cs
rename to src/EFCore.Relational/Metadata/Conventions/RelationalDbFunctionAttributeConvention.cs
index e0acd9874a5..8623ebb17de 100644
--- a/src/EFCore.Relational/Metadata/Conventions/RelationalDbFunctionConvention.cs
+++ b/src/EFCore.Relational/Metadata/Conventions/RelationalDbFunctionAttributeConvention.cs
@@ -12,17 +12,17 @@
namespace Microsoft.EntityFrameworkCore.Metadata.Conventions
{
///
- /// A convention that configures the name and schema for a based on the applied
+ /// A convention that configures model function mappings based on public static methods on the context marked with
/// .
///
- public class RelationalDbFunctionConvention : IModelAnnotationChangedConvention
+ public class RelationalDbFunctionAttributeConvention : IModelInitializedConvention, IModelAnnotationChangedConvention
{
///
- /// Creates a new instance of .
+ /// Creates a new instance of .
///
/// Parameter object containing dependencies for this convention.
/// Parameter object containing relational dependencies for this convention.
- public RelationalDbFunctionConvention(
+ public RelationalDbFunctionAttributeConvention(
[NotNull] ProviderConventionSetBuilderDependencies dependencies,
[NotNull] RelationalConventionSetBuilderDependencies relationalDependencies)
{
@@ -34,6 +34,31 @@ public RelationalDbFunctionConvention(
///
protected virtual ProviderConventionSetBuilderDependencies Dependencies { get; }
+ ///
+ /// Called after a model is initialized.
+ ///
+ /// The builder for the model.
+ /// Additional information associated with convention execution.
+ public virtual void ProcessModelInitialized(IConventionModelBuilder modelBuilder, IConventionContext context)
+ {
+ var contextType = Dependencies.ContextType;
+ while (contextType != null
+ && contextType != typeof(DbContext))
+ {
+ var functions = contextType.GetMethods(
+ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance
+ | BindingFlags.Static | BindingFlags.DeclaredOnly)
+ .Where(mi => mi.IsDefined(typeof(DbFunctionAttribute)));
+
+ foreach (var function in functions)
+ {
+ modelBuilder.HasDbFunction(function);
+ }
+
+ contextType = contextType.BaseType;
+ }
+ }
+
///
/// Called after an annotation is changed on an model.
///
diff --git a/src/EFCore.Relational/Metadata/Conventions/TableNameFromDbSetConvention.cs b/src/EFCore.Relational/Metadata/Conventions/TableNameFromDbSetConvention.cs
index ad82d21dc22..bae5c258aae 100644
--- a/src/EFCore.Relational/Metadata/Conventions/TableNameFromDbSetConvention.cs
+++ b/src/EFCore.Relational/Metadata/Conventions/TableNameFromDbSetConvention.cs
@@ -13,7 +13,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions
///
/// A convention that configures the table name based on the property name.
///
- public class TableNameFromDbSetConvention : IEntityTypeBaseTypeChangedConvention
+ public class TableNameFromDbSetConvention : IEntityTypeAddedConvention, IEntityTypeBaseTypeChangedConvention
{
private readonly IDictionary _sets;
@@ -60,11 +60,30 @@ public virtual void ProcessEntityTypeBaseTypeChanged(
}
else if (oldBaseType != null
&& newBaseType == null
+ && entityType.ClrType != null
&& _sets.ContainsKey(entityType.ClrType))
{
entityTypeBuilder.ToTable(_sets[entityType.ClrType].Name);
}
}
}
+
+ ///
+ /// Called after an entity type is added to the model.
+ ///
+ /// The builder for the entity type.
+ /// Additional information associated with convention execution.
+ public virtual void ProcessEntityTypeAdded(
+ IConventionEntityTypeBuilder entityTypeBuilder,
+ IConventionContext context)
+ {
+ var entityType = entityTypeBuilder.Metadata;
+ if (entityType.BaseType == null
+ && entityType.ClrType != null
+ && _sets.ContainsKey(entityType.ClrType))
+ {
+ entityTypeBuilder.ToTable(_sets[entityType.ClrType].Name);
+ }
+ }
}
}
diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs
index 3ab995d4615..4774a98ea4a 100644
--- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs
+++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerConventionSetBuilder.cs
@@ -94,7 +94,7 @@ public override ConventionSet CreateConventionSet()
ReplaceConvention(
conventionSet.ModelAnnotationChangedConventions,
- (RelationalDbFunctionConvention)new SqlServerDbFunctionConvention(Dependencies, RelationalDependencies));
+ (RelationalDbFunctionAttributeConvention)new SqlServerDbFunctionAttributeConvention(Dependencies, RelationalDependencies));
ReplaceConvention(conventionSet.ModelFinalizedConventions, storeGenerationConvention);
diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerDbFunctionConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerDbFunctionAttributeConvention.cs
similarity index 82%
rename from src/EFCore.SqlServer/Metadata/Conventions/SqlServerDbFunctionConvention.cs
rename to src/EFCore.SqlServer/Metadata/Conventions/SqlServerDbFunctionAttributeConvention.cs
index 73a0d2688ce..dba56194f0f 100644
--- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerDbFunctionConvention.cs
+++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerDbFunctionAttributeConvention.cs
@@ -10,17 +10,17 @@
namespace Microsoft.EntityFrameworkCore.Metadata.Conventions
{
///
- /// A convention that configures the name and schema for a based on the applied
- /// and the default schema as 'dbo'.
+ /// A convention that configures model function mappings based on public static methods on the context marked with
+ /// and sets the default schema to 'dbo'.
///
- public class SqlServerDbFunctionConvention : RelationalDbFunctionConvention
+ public class SqlServerDbFunctionAttributeConvention : RelationalDbFunctionAttributeConvention
{
///
- /// Creates a new instance of .
+ /// Creates a new instance of .
///
/// Parameter object containing dependencies for this convention.
/// Parameter object containing relational dependencies for this convention.
- public SqlServerDbFunctionConvention(
+ public SqlServerDbFunctionAttributeConvention(
[NotNull] ProviderConventionSetBuilderDependencies dependencies,
[NotNull] RelationalConventionSetBuilderDependencies relationalDependencies)
: base(dependencies, relationalDependencies)
diff --git a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerIndexConvention.cs b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerIndexConvention.cs
index 2123a0a1edc..b2707ec6de6 100644
--- a/src/EFCore.SqlServer/Metadata/Conventions/SqlServerIndexConvention.cs
+++ b/src/EFCore.SqlServer/Metadata/Conventions/SqlServerIndexConvention.cs
@@ -27,7 +27,7 @@ public class SqlServerIndexConvention :
private readonly ISqlGenerationHelper _sqlGenerationHelper;
///
- /// Creates a new instance of .
+ /// Creates a new instance of .
///
/// Parameter object containing dependencies for this convention.
/// Parameter object containing relational dependencies for this convention.
diff --git a/src/EFCore/Infrastructure/ModelCustomizer.cs b/src/EFCore/Infrastructure/ModelCustomizer.cs
index 4e16d35ab96..736b6ab4913 100644
--- a/src/EFCore/Infrastructure/ModelCustomizer.cs
+++ b/src/EFCore/Infrastructure/ModelCustomizer.cs
@@ -1,7 +1,6 @@
// 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 JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Utilities;
using Microsoft.Extensions.DependencyInjection;
@@ -54,29 +53,7 @@ public ModelCustomizer([NotNull] ModelCustomizerDependencies dependencies)
///
public virtual void Customize(ModelBuilder modelBuilder, DbContext context)
{
- FindSets(modelBuilder, context.GetType());
-
context.OnModelCreating(modelBuilder);
}
-
- ///
- /// Adds the entity types found in properties on the context to the model.
- ///
- /// The being used to build the model.
- /// The context type to find properties on.
- protected virtual void FindSets([NotNull] ModelBuilder modelBuilder, [NotNull] Type contextType)
- {
- foreach (var setInfo in Dependencies.SetFinder.FindSets(contextType))
- {
- if (setInfo.IsKeyless)
- {
- modelBuilder.Entity(setInfo.ClrType).HasNoKey();
- }
- else
- {
- modelBuilder.Entity(setInfo.ClrType);
- }
- }
- }
}
}
diff --git a/src/EFCore/Metadata/Conventions/DbSetFindingConvention.cs b/src/EFCore/Metadata/Conventions/DbSetFindingConvention.cs
new file mode 100644
index 00000000000..4e3f79ee57b
--- /dev/null
+++ b/src/EFCore/Metadata/Conventions/DbSetFindingConvention.cs
@@ -0,0 +1,50 @@
+// 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 JetBrains.Annotations;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure;
+
+namespace Microsoft.EntityFrameworkCore.Metadata.Conventions
+{
+ ///
+ /// A convention that adds entity types based on the properties defined on the
+ /// derived class.
+ ///
+ public class DbSetFindingConvention : IModelInitializedConvention
+ {
+ ///
+ /// Creates a new instance of .
+ ///
+ /// Parameter object containing dependencies for this convention.
+ public DbSetFindingConvention([NotNull] ProviderConventionSetBuilderDependencies dependencies)
+ {
+ Dependencies = dependencies;
+ }
+
+ ///
+ /// Parameter object containing service dependencies.
+ ///
+ protected virtual ProviderConventionSetBuilderDependencies Dependencies { get; }
+
+ ///
+ /// Called after a model is initialized.
+ ///
+ /// The builder for the model.
+ /// Additional information associated with convention execution.
+ public virtual void ProcessModelInitialized(IConventionModelBuilder modelBuilder, IConventionContext context)
+ {
+ foreach (var setInfo in Dependencies.SetFinder.FindSets(Dependencies.ContextType))
+ {
+ if (setInfo.IsKeyless)
+ {
+ modelBuilder.Entity(setInfo.ClrType, fromDataAnnotation: true).HasNoKey(fromDataAnnotation: true);
+ }
+ else
+ {
+ modelBuilder.Entity(setInfo.ClrType, fromDataAnnotation: true);
+ }
+ }
+ }
+ }
+}
diff --git a/src/EFCore/Metadata/Conventions/Infrastructure/ProviderConventionSetBuilder.cs b/src/EFCore/Metadata/Conventions/Infrastructure/ProviderConventionSetBuilder.cs
index 9da10e28d7a..adfca84ccf4 100644
--- a/src/EFCore/Metadata/Conventions/Infrastructure/ProviderConventionSetBuilder.cs
+++ b/src/EFCore/Metadata/Conventions/Infrastructure/ProviderConventionSetBuilder.cs
@@ -160,6 +160,8 @@ public virtual ConventionSet CreateConventionSet()
conventionSet.ForeignKeyOwnershipChangedConventions.Add(keyDiscoveryConvention);
conventionSet.ForeignKeyOwnershipChangedConventions.Add(relationshipDiscoveryConvention);
+ conventionSet.ModelInitializedConventions.Add(new DbSetFindingConvention(Dependencies));
+
conventionSet.ModelFinalizedConventions.Add(new ModelCleanupConvention(Dependencies));
conventionSet.ModelFinalizedConventions.Add(keyAttributeConvention);
conventionSet.ModelFinalizedConventions.Add(foreignKeyAttributeConvention);
diff --git a/test/EFCore.Cosmos.Tests/TestUtilities/CosmosTestHelpers.cs b/test/EFCore.Cosmos.Tests/TestUtilities/CosmosTestHelpers.cs
index dc4dd7e57df..37480ba4279 100644
--- a/test/EFCore.Cosmos.Tests/TestUtilities/CosmosTestHelpers.cs
+++ b/test/EFCore.Cosmos.Tests/TestUtilities/CosmosTestHelpers.cs
@@ -20,29 +20,12 @@ protected CosmosTestHelpers()
public static CosmosTestHelpers Instance { get; } = new CosmosTestHelpers();
public override IServiceCollection AddProviderServices(IServiceCollection services)
- {
- return services.AddEntityFrameworkCosmos();
- }
-
- public override IModelValidator CreateModelValidator()
- {
- var typeMappingSource = new CosmosTypeMappingSource(
- TestServiceFactory.Instance.Create());
-
- return new ModelValidator(
- new ModelValidatorDependencies(
- typeMappingSource,
- new MemberClassifier(
- typeMappingSource,
- TestServiceFactory.Instance.Create())));
- }
+ => services.AddEntityFrameworkCosmos();
protected override void UseProviderOptions(DbContextOptionsBuilder optionsBuilder)
- {
- optionsBuilder.UseCosmos(
+ => optionsBuilder.UseCosmos(
TestEnvironment.DefaultConnection,
TestEnvironment.AuthToken,
"UnitTests");
- }
}
}
diff --git a/test/EFCore.InMemory.FunctionalTests/TestUtilities/InMemoryTestHelpers.cs b/test/EFCore.InMemory.FunctionalTests/TestUtilities/InMemoryTestHelpers.cs
index 87b199fda0a..3eb205f852c 100644
--- a/test/EFCore.InMemory.FunctionalTests/TestUtilities/InMemoryTestHelpers.cs
+++ b/test/EFCore.InMemory.FunctionalTests/TestUtilities/InMemoryTestHelpers.cs
@@ -26,19 +26,6 @@ public override IServiceCollection AddProviderServices(IServiceCollection servic
protected override void UseProviderOptions(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseInMemoryDatabase(nameof(InMemoryTestHelpers));
- public override IModelValidator CreateModelValidator()
- {
- var typeMappingSource = new InMemoryTypeMappingSource(
- TestServiceFactory.Instance.Create());
-
- return new ModelValidator(
- new ModelValidatorDependencies(
- typeMappingSource,
- new MemberClassifier(
- typeMappingSource,
- TestServiceFactory.Instance.Create())));
- }
-
public override LoggingDefinitions LoggingDefinitions { get; } = new InMemoryLoggingDefinitions();
}
}
diff --git a/test/EFCore.Relational.Tests/Metadata/Conventions/Internal/RelationalPropertyMappingValidationConventionTest.cs b/test/EFCore.Relational.Tests/Metadata/Conventions/Internal/RelationalPropertyMappingValidationConventionTest.cs
index b7fd446f0ba..57cdaa5efab 100644
--- a/test/EFCore.Relational.Tests/Metadata/Conventions/Internal/RelationalPropertyMappingValidationConventionTest.cs
+++ b/test/EFCore.Relational.Tests/Metadata/Conventions/Internal/RelationalPropertyMappingValidationConventionTest.cs
@@ -5,6 +5,7 @@
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
+using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.TestUtilities;
using Xunit;
@@ -16,7 +17,7 @@ public class RelationalPropertyMappingValidationConventionTest : PropertyMapping
[Fact]
public void Throws_when_added_property_is_not_mapped_to_store()
{
- var modelBuilder = new InternalModelBuilder(new Model());
+ var modelBuilder = CreateConventionlessModelBuilder().GetInfrastructure();
var entityTypeBuilder = modelBuilder.Entity(typeof(NonPrimitiveAsPropertyEntity), ConfigurationSource.Convention);
entityTypeBuilder.Property(typeof(Tuple), "LongProperty", ConfigurationSource.Explicit);
entityTypeBuilder.Ignore(nameof(NonPrimitiveAsPropertyEntity.Property), ConfigurationSource.Explicit);
@@ -30,7 +31,7 @@ public void Throws_when_added_property_is_not_mapped_to_store()
[Fact]
public void Throws_when_added_property_is_not_mapped_to_store_even_if_configured_to_use_column_type()
{
- var modelBuilder = new InternalModelBuilder(new Model());
+ var modelBuilder = CreateConventionlessModelBuilder().GetInfrastructure();
var entityTypeBuilder = modelBuilder.Entity(typeof(NonPrimitiveNonNavigationAsPropertyEntity), ConfigurationSource.Convention);
entityTypeBuilder.Property(typeof(Tuple), "LongProperty", ConfigurationSource.Explicit)
.HasColumnType("some_int_mapping");
@@ -43,5 +44,20 @@ public void Throws_when_added_property_is_not_mapped_to_store_even_if_configured
}
protected override TestHelpers TestHelpers => RelationalTestHelpers.Instance;
+
+ protected override IModelValidator CreateModelValidator()
+ {
+ var typeMappingSource = new TestRelationalTypeMappingSource(
+ TestServiceFactory.Instance.Create(),
+ TestServiceFactory.Instance.Create());
+
+ return new RelationalModelValidator(
+ new ModelValidatorDependencies(
+ typeMappingSource,
+ new MemberClassifier(
+ typeMappingSource,
+ TestServiceFactory.Instance.Create())),
+ new RelationalModelValidatorDependencies(typeMappingSource));
+ }
}
}
diff --git a/test/EFCore.Relational.Tests/Metadata/DbFunctionMetadataTests.cs b/test/EFCore.Relational.Tests/Metadata/DbFunctionMetadataTests.cs
index 76b66f18199..bcc730bce33 100644
--- a/test/EFCore.Relational.Tests/Metadata/DbFunctionMetadataTests.cs
+++ b/test/EFCore.Relational.Tests/Metadata/DbFunctionMetadataTests.cs
@@ -228,11 +228,8 @@ var dup2methodInfo
[Fact]
public virtual void Finds_dbFunctions_on_dbContext()
{
- var modelBuilder = GetModelBuilder();
-
- var customizer = new RelationalModelCustomizer(new ModelCustomizerDependencies(new DbSetFinder()));
-
- customizer.Customize(modelBuilder, new MyDerivedContext());
+ var context = new MyDerivedContext();
+ var modelBuilder = GetModelBuilder(context);
foreach (var function in MyBaseContext.FunctionNames)
{
@@ -488,12 +485,15 @@ public virtual void Set_empty_function_name_throws()
expectedMessage, Assert.Throws(() => modelBuilder.HasDbFunction(MethodAmi).HasName("")).Message);
}
- private ModelBuilder GetModelBuilder()
+ private ModelBuilder GetModelBuilder(DbContext dbContext = null)
{
var conventionSet = new ConventionSet();
- conventionSet.ModelAnnotationChangedConventions.Add(
- new RelationalDbFunctionConvention(CreateDependencies(), CreateRelationalDependencies()));
+ var dbFunctionAttributeConvention =new RelationalDbFunctionAttributeConvention(
+ CreateDependencies().With(new CurrentDbContext (dbContext ?? new DbContext(new DbContextOptions()))),
+ CreateRelationalDependencies());
+ conventionSet.ModelInitializedConventions.Add(dbFunctionAttributeConvention);
+ conventionSet.ModelAnnotationChangedConventions.Add(dbFunctionAttributeConvention);
return new ModelBuilder(conventionSet);
}
diff --git a/test/EFCore.Relational.Tests/TestUtilities/RelationalTestHelpers.cs b/test/EFCore.Relational.Tests/TestUtilities/RelationalTestHelpers.cs
index 62c2610959a..bd222a842cf 100644
--- a/test/EFCore.Relational.Tests/TestUtilities/RelationalTestHelpers.cs
+++ b/test/EFCore.Relational.Tests/TestUtilities/RelationalTestHelpers.cs
@@ -3,9 +3,6 @@
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Metadata;
-using Microsoft.EntityFrameworkCore.Metadata.Internal;
-using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.TestUtilities.FakeProvider;
using Microsoft.Extensions.DependencyInjection;
@@ -31,21 +28,6 @@ protected override void UseProviderOptions(DbContextOptionsBuilder optionsBuilde
extension.WithConnection(new FakeDbConnection("Database=Fake")));
}
- public override IModelValidator CreateModelValidator()
- {
- var typeMappingSource = new TestRelationalTypeMappingSource(
- TestServiceFactory.Instance.Create(),
- TestServiceFactory.Instance.Create());
-
- return new RelationalModelValidator(
- new ModelValidatorDependencies(
- typeMappingSource,
- new MemberClassifier(
- typeMappingSource,
- TestServiceFactory.Instance.Create())),
- new RelationalModelValidatorDependencies(typeMappingSource));
- }
-
public override LoggingDefinitions LoggingDefinitions { get; } = new TestRelationalLoggingDefinitions();
}
}
diff --git a/test/EFCore.Specification.Tests/TestUtilities/TestHelpers.cs b/test/EFCore.Specification.Tests/TestUtilities/TestHelpers.cs
index 35e91011439..556dde1d76f 100644
--- a/test/EFCore.Specification.Tests/TestUtilities/TestHelpers.cs
+++ b/test/EFCore.Specification.Tests/TestUtilities/TestHelpers.cs
@@ -229,8 +229,6 @@ public ModelBuilder CreateConventionBuilder(
return new ModelBuilder(conventionSet);
}
- public abstract IModelValidator CreateModelValidator();
-
public virtual LoggingDefinitions LoggingDefinitions { get; } = new TestLoggingDefinitions();
public InternalEntityEntry CreateInternalEntry(
diff --git a/test/EFCore.SqlServer.FunctionalTests/SqlServerDbFunctionMetadataTests.cs b/test/EFCore.SqlServer.FunctionalTests/SqlServerDbFunctionMetadataTests.cs
index 5e07f5c075e..3f0db8fad06 100644
--- a/test/EFCore.SqlServer.FunctionalTests/SqlServerDbFunctionMetadataTests.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/SqlServerDbFunctionMetadataTests.cs
@@ -69,7 +69,7 @@ private ModelBuilder GetModelBuilder()
var conventionSet = new ConventionSet();
conventionSet.ModelAnnotationChangedConventions.Add(
- new SqlServerDbFunctionConvention(CreateDependencies(), CreateRelationalDependencies()));
+ new SqlServerDbFunctionAttributeConvention(CreateDependencies(), CreateRelationalDependencies()));
return new ModelBuilder(conventionSet);
}
diff --git a/test/EFCore.SqlServer.FunctionalTests/TestUtilities/SqlServerTestHelpers.cs b/test/EFCore.SqlServer.FunctionalTests/TestUtilities/SqlServerTestHelpers.cs
index 741096a5c28..fc242e7756c 100644
--- a/test/EFCore.SqlServer.FunctionalTests/TestUtilities/SqlServerTestHelpers.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/TestUtilities/SqlServerTestHelpers.cs
@@ -28,21 +28,6 @@ public override IServiceCollection AddProviderServices(IServiceCollection servic
protected override void UseProviderOptions(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseSqlServer(new SqlConnection("Database=DummyDatabase"));
- public override IModelValidator CreateModelValidator()
- {
- var typeMappingSource = new SqlServerTypeMappingSource(
- TestServiceFactory.Instance.Create(),
- TestServiceFactory.Instance.Create());
-
- return new SqlServerModelValidator(
- new ModelValidatorDependencies(
- typeMappingSource,
- new MemberClassifier(
- typeMappingSource,
- TestServiceFactory.Instance.Create())),
- new RelationalModelValidatorDependencies(typeMappingSource));
- }
-
public override LoggingDefinitions LoggingDefinitions { get; } = new SqlServerLoggingDefinitions();
}
}
diff --git a/test/EFCore.Sqlite.FunctionalTests/TestUtilities/SqliteTestHelpers.cs b/test/EFCore.Sqlite.FunctionalTests/TestUtilities/SqliteTestHelpers.cs
index 85e25af29ac..a5c2b832d8f 100644
--- a/test/EFCore.Sqlite.FunctionalTests/TestUtilities/SqliteTestHelpers.cs
+++ b/test/EFCore.Sqlite.FunctionalTests/TestUtilities/SqliteTestHelpers.cs
@@ -28,21 +28,6 @@ public override IServiceCollection AddProviderServices(IServiceCollection servic
protected override void UseProviderOptions(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseSqlite(new SqliteConnection("Data Source=:memory:"));
- public override IModelValidator CreateModelValidator()
- {
- var typeMappingSource = new SqliteTypeMappingSource(
- TestServiceFactory.Instance.Create(),
- TestServiceFactory.Instance.Create());
-
- return new SqliteModelValidator(
- new ModelValidatorDependencies(
- typeMappingSource,
- new MemberClassifier(
- typeMappingSource,
- TestServiceFactory.Instance.Create())),
- new RelationalModelValidatorDependencies(typeMappingSource));
- }
-
public override LoggingDefinitions LoggingDefinitions { get; } = new SqliteLoggingDefinitions();
}
}
diff --git a/test/EFCore.Tests/Metadata/Conventions/Internal/PropertyMappingValidationConventionTest.cs b/test/EFCore.Tests/Metadata/Conventions/Internal/PropertyMappingValidationConventionTest.cs
index 3062ade91c4..7fa96ce3b75 100644
--- a/test/EFCore.Tests/Metadata/Conventions/Internal/PropertyMappingValidationConventionTest.cs
+++ b/test/EFCore.Tests/Metadata/Conventions/Internal/PropertyMappingValidationConventionTest.cs
@@ -8,20 +8,22 @@
using System.Threading;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.InMemory.Storage.Internal;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
+using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.TestUtilities;
using Xunit;
// ReSharper disable InconsistentNaming
namespace Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal
{
- public class PropertyMappingValidationConventionTest
+ public class PropertyMappingValidationConventionTest : ModelValidatorTestBase
{
[Fact]
public virtual void Throws_when_added_property_is_not_of_primitive_type()
{
- var modelBuilder = new InternalModelBuilder(new Model());
+ var modelBuilder = CreateConventionlessModelBuilder().GetInfrastructure();
var entityTypeBuilder = modelBuilder.Entity(typeof(NonPrimitiveAsPropertyEntity), ConfigurationSource.Convention);
entityTypeBuilder.Property(typeof(NavigationAsProperty), nameof(NonPrimitiveAsPropertyEntity.Property), ConfigurationSource.Convention);
@@ -36,7 +38,7 @@ public virtual void Throws_when_added_property_is_not_of_primitive_type()
[Fact]
public virtual void Does_not_throw_when_added_shadow_property_by_convention_is_not_of_primitive_type()
{
- var modelBuilder = new InternalModelBuilder(new Model());
+ var modelBuilder = CreateConventionlessModelBuilder().GetInfrastructure();
var entityTypeBuilder = modelBuilder.Entity(typeof(NonPrimitiveAsPropertyEntity), ConfigurationSource.Convention);
entityTypeBuilder.Property(typeof(NavigationAsProperty), "ShadowProperty", ConfigurationSource.Convention);
entityTypeBuilder.Ignore(nameof(NonPrimitiveAsPropertyEntity.Property), ConfigurationSource.Explicit);
@@ -47,7 +49,7 @@ public virtual void Does_not_throw_when_added_shadow_property_by_convention_is_n
[Fact]
public virtual void Throws_when_primitive_type_property_is_not_added_or_ignored()
{
- var modelBuilder = new InternalModelBuilder(new Model());
+ var modelBuilder = CreateConventionlessModelBuilder().GetInfrastructure();
modelBuilder.Entity(typeof(PrimitivePropertyEntity), ConfigurationSource.Convention);
Assert.Equal(
@@ -59,7 +61,7 @@ public virtual void Throws_when_primitive_type_property_is_not_added_or_ignored(
[Fact]
public virtual void Throws_when_nonprimitive_value_type_property_is_not_added_or_ignored()
{
- var modelBuilder = new InternalModelBuilder(new Model());
+ var modelBuilder = CreateConventionlessModelBuilder().GetInfrastructure();
modelBuilder.Entity(typeof(NonPrimitiveValueTypePropertyEntity), ConfigurationSource.Convention);
Assert.Equal(
@@ -71,7 +73,7 @@ public virtual void Throws_when_nonprimitive_value_type_property_is_not_added_or
[Fact]
public virtual void Throws_when_keyless_type_property_is_not_added_or_ignored()
{
- var modelBuilder = new InternalModelBuilder(new Model());
+ var modelBuilder = CreateConventionlessModelBuilder().GetInfrastructure();
modelBuilder.Entity(typeof(NonPrimitiveReferenceTypePropertyEntity), ConfigurationSource.Convention);
Assert.Equal(
@@ -85,7 +87,7 @@ public virtual void Throws_when_keyless_type_property_is_not_added_or_ignored()
[Fact]
public virtual void Does_not_throw_when_primitive_type_property_is_added()
{
- var modelBuilder = new InternalModelBuilder(new Model());
+ var modelBuilder = CreateConventionlessModelBuilder().GetInfrastructure();
var entityTypeBuilder = modelBuilder.Entity(typeof(PrimitivePropertyEntity), ConfigurationSource.Convention);
entityTypeBuilder.Property(typeof(int), "Property", ConfigurationSource.Convention);
@@ -95,7 +97,7 @@ public virtual void Does_not_throw_when_primitive_type_property_is_added()
[Fact]
public virtual void Does_not_throw_when_primitive_type_property_is_ignored()
{
- var modelBuilder = new InternalModelBuilder(new Model());
+ var modelBuilder = CreateConventionlessModelBuilder().GetInfrastructure();
var entityTypeBuilder = modelBuilder.Entity(typeof(PrimitivePropertyEntity), ConfigurationSource.Convention);
entityTypeBuilder.Ignore("Property", ConfigurationSource.DataAnnotation);
@@ -105,7 +107,7 @@ public virtual void Does_not_throw_when_primitive_type_property_is_ignored()
[Fact]
public virtual void Throws_when_navigation_is_not_added_or_ignored()
{
- var modelBuilder = new InternalModelBuilder(new Model());
+ var modelBuilder = CreateConventionlessModelBuilder().GetInfrastructure();
modelBuilder.Entity(typeof(NavigationEntity), ConfigurationSource.Convention);
modelBuilder.Entity(typeof(PrimitivePropertyEntity), ConfigurationSource.Convention);
@@ -118,7 +120,7 @@ public virtual void Throws_when_navigation_is_not_added_or_ignored()
[Fact]
public virtual void Does_not_throw_when_navigation_is_added()
{
- var modelBuilder = new InternalModelBuilder(new Model());
+ var modelBuilder = CreateConventionlessModelBuilder().GetInfrastructure();
var entityTypeBuilder = modelBuilder.Entity(typeof(NavigationEntity), ConfigurationSource.Convention);
var referencedEntityTypeBuilder = modelBuilder.Entity(typeof(PrimitivePropertyEntity), ConfigurationSource.Convention);
referencedEntityTypeBuilder.Ignore("Property", ConfigurationSource.DataAnnotation);
@@ -130,7 +132,7 @@ public virtual void Does_not_throw_when_navigation_is_added()
[Fact]
public virtual void Does_not_throw_when_navigation_is_ignored()
{
- var modelBuilder = new InternalModelBuilder(new Model());
+ var modelBuilder = CreateConventionlessModelBuilder().GetInfrastructure();
var entityTypeBuilder = modelBuilder.Entity(typeof(NavigationEntity), ConfigurationSource.Convention);
entityTypeBuilder.Ignore("Navigation", ConfigurationSource.DataAnnotation);
@@ -140,7 +142,7 @@ public virtual void Does_not_throw_when_navigation_is_ignored()
[Fact]
public virtual void Does_not_throw_when_navigation_target_entity_is_ignored()
{
- var modelBuilder = new InternalModelBuilder(new Model());
+ var modelBuilder = CreateConventionlessModelBuilder().GetInfrastructure();
modelBuilder.Entity(typeof(NavigationEntity), ConfigurationSource.Convention);
modelBuilder.Ignore(typeof(PrimitivePropertyEntity), ConfigurationSource.Convention);
@@ -150,7 +152,7 @@ public virtual void Does_not_throw_when_navigation_target_entity_is_ignored()
[Fact]
public virtual void Does_not_throw_when_explicit_navigation_is_not_added()
{
- var modelBuilder = new InternalModelBuilder(new Model());
+ var modelBuilder = CreateConventionlessModelBuilder().GetInfrastructure();
var entityTypeBuilder = modelBuilder.Entity(typeof(ExplicitNavigationEntity), ConfigurationSource.Convention);
var referencedEntityTypeBuilder = modelBuilder.Entity(typeof(PrimitivePropertyEntity), ConfigurationSource.Convention);
referencedEntityTypeBuilder.Ignore("Property", ConfigurationSource.DataAnnotation);
@@ -163,7 +165,7 @@ public virtual void Does_not_throw_when_explicit_navigation_is_not_added()
[Fact]
public virtual void Throws_when_interface_type_property_is_not_added_or_ignored()
{
- var modelBuilder = new InternalModelBuilder(new Model());
+ var modelBuilder = CreateConventionlessModelBuilder().GetInfrastructure();
modelBuilder.Entity(typeof(InterfaceNavigationEntity), ConfigurationSource.Convention);
Assert.Equal(
@@ -177,7 +179,7 @@ public virtual void Throws_when_interface_type_property_is_not_added_or_ignored(
[Fact]
public virtual void Does_not_throw_when_non_candidate_property_is_not_added()
{
- var modelBuilder = new InternalModelBuilder(new Model());
+ var modelBuilder = CreateConventionlessModelBuilder().GetInfrastructure();
modelBuilder.Entity(typeof(NonCandidatePropertyEntity), ConfigurationSource.Convention);
CreatePropertyMappingValidator()(modelBuilder.Metadata);
@@ -185,7 +187,7 @@ public virtual void Does_not_throw_when_non_candidate_property_is_not_added()
protected virtual Action CreatePropertyMappingValidator()
{
- var validator = TestHelpers.CreateModelValidator();
+ var validator = CreateModelValidator();
var logger = new TestLogger();
var validatePropertyMappingMethod = typeof(ModelValidator).GetRuntimeMethods().Single(e => e.Name == "ValidatePropertyMapping");
@@ -207,7 +209,18 @@ protected virtual Action CreatePropertyMappingValidator()
};
}
- protected virtual TestHelpers TestHelpers => InMemoryTestHelpers.Instance;
+ protected virtual IModelValidator CreateModelValidator()
+ {
+ var typeMappingSource = new InMemoryTypeMappingSource(
+ TestServiceFactory.Instance.Create());
+
+ return new ModelValidator(
+ new ModelValidatorDependencies(
+ typeMappingSource,
+ new MemberClassifier(
+ typeMappingSource,
+ TestServiceFactory.Instance.Create())));
+ }
protected class NonPrimitiveNonNavigationAsPropertyEntity
{
diff --git a/test/EFCore.Tests/ModelSourceTest.cs b/test/EFCore.Tests/ModelSourceTest.cs
index 8a65fee09e6..82ac7b664a2 100644
--- a/test/EFCore.Tests/ModelSourceTest.cs
+++ b/test/EFCore.Tests/ModelSourceTest.cs
@@ -13,6 +13,7 @@
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal;
using Microsoft.EntityFrameworkCore.TestUtilities;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
@@ -23,9 +24,6 @@ namespace Microsoft.EntityFrameworkCore
{
public class ModelSourceTest
{
- private readonly IModelValidator _coreModelValidator
- = InMemoryTestHelpers.Instance.CreateContextServices().GetRequiredService();
-
private readonly IConventionSetBuilder _nullConventionSetBuilder
= new NullConventionSetBuilder();
@@ -76,10 +74,13 @@ protected internal override void OnConfiguring(DbContextOptionsBuilder optionsBu
public void Adds_all_entities_based_on_all_distinct_entity_types_found()
{
var setFinder = new FakeSetFinder();
- var logger = new TestLogger();
var model = CreateDefaultModelSource(setFinder)
- .GetModel(InMemoryTestHelpers.Instance.CreateContext(), _nullConventionSetBuilder);
+ .GetModel(
+ InMemoryTestHelpers.Instance.CreateContext(),
+ new RuntimeConventionSetBuilder(new ProviderConventionSetBuilder(
+ InMemoryTestHelpers.Instance.CreateContextServices().GetRequiredService()
+ .With(setFinder)), new List()));
Assert.Equal(
new[] { typeof(SetA).DisplayName(), typeof(SetB).DisplayName() },
@@ -126,7 +127,6 @@ private class SetB
public void Caches_model_by_context_type()
{
var modelSource = CreateDefaultModelSource(new DbSetFinder());
- var logger = new TestLogger();
var model1 = modelSource.GetModel(new Context1(), _nullConventionSetBuilder);
var model2 = modelSource.GetModel(new Context2(), _nullConventionSetBuilder);
@@ -140,7 +140,6 @@ public void Caches_model_by_context_type()
public void Stores_model_version_information_as_annotation_on_model()
{
var modelSource = CreateDefaultModelSource(new DbSetFinder());
- var logger = new TestLogger();
var model = modelSource.GetModel(new Context1(), _nullConventionSetBuilder);
var packageVersion = typeof(Context1).Assembly.GetCustomAttributes()