diff --git a/EFCore.Runtime.sln b/EFCore.Runtime.sln index a23561004d9..0d71fdf55d3 100644 --- a/EFCore.Runtime.sln +++ b/EFCore.Runtime.sln @@ -54,6 +54,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution tools\Resources.tt = tools\Resources.tt EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EFCore.Attributes", "src\EFCore.Attributes\EFCore.Attributes.csproj", "{92C1AEF8-D4FC-4631-98B1-F16FB7103398}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -128,6 +130,10 @@ Global {7583E3F0-8B29-4BEA-A55E-E8B66E6FD508}.Debug|Any CPU.Build.0 = Debug|Any CPU {7583E3F0-8B29-4BEA-A55E-E8B66E6FD508}.Release|Any CPU.ActiveCfg = Release|Any CPU {7583E3F0-8B29-4BEA-A55E-E8B66E6FD508}.Release|Any CPU.Build.0 = Release|Any CPU + {92C1AEF8-D4FC-4631-98B1-F16FB7103398}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {92C1AEF8-D4FC-4631-98B1-F16FB7103398}.Debug|Any CPU.Build.0 = Debug|Any CPU + {92C1AEF8-D4FC-4631-98B1-F16FB7103398}.Release|Any CPU.ActiveCfg = Release|Any CPU + {92C1AEF8-D4FC-4631-98B1-F16FB7103398}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -150,6 +156,7 @@ Global {07FA2B15-A6A5-4292-A096-7771FB32EEDA} = {258D5057-81B9-40EC-A872-D21E27452749} {D3D0A8E8-EC2F-4E01-8650-8554E186A66F} = {CE6B50B2-34AE-44C9-940A-4E48C3E1B3BC} {7583E3F0-8B29-4BEA-A55E-E8B66E6FD508} = {258D5057-81B9-40EC-A872-D21E27452749} + {92C1AEF8-D4FC-4631-98B1-F16FB7103398} = {CE6B50B2-34AE-44C9-940A-4E48C3E1B3BC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {EC8BCF1F-A206-4420-A292-3E3F2A4CDC54} diff --git a/EFCore.sln b/EFCore.sln index dd11ca117b1..439f2fccffc 100644 --- a/EFCore.sln +++ b/EFCore.sln @@ -83,6 +83,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Directory.Build.targets = Directory.Build.targets EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.Attributes", "src\EFCore.Attributes\EFCore.Attributes.csproj", "{11B51A41-47CB-4EDB-9D8A-17095A65034A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -311,6 +313,14 @@ Global {9511216F-EC10-480D-AA8D-F72312C96962}.Release|Any CPU.Build.0 = Release|Any CPU {9511216F-EC10-480D-AA8D-F72312C96962}.ReleaseNoBenchmarks|Any CPU.ActiveCfg = Release|Any CPU {9511216F-EC10-480D-AA8D-F72312C96962}.ReleaseNoBenchmarks|Any CPU.Build.0 = Release|Any CPU + {11B51A41-47CB-4EDB-9D8A-17095A65034A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {11B51A41-47CB-4EDB-9D8A-17095A65034A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {11B51A41-47CB-4EDB-9D8A-17095A65034A}.DebugNoBenchmarks|Any CPU.ActiveCfg = Debug|Any CPU + {11B51A41-47CB-4EDB-9D8A-17095A65034A}.DebugNoBenchmarks|Any CPU.Build.0 = Debug|Any CPU + {11B51A41-47CB-4EDB-9D8A-17095A65034A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {11B51A41-47CB-4EDB-9D8A-17095A65034A}.Release|Any CPU.Build.0 = Release|Any CPU + {11B51A41-47CB-4EDB-9D8A-17095A65034A}.ReleaseNoBenchmarks|Any CPU.ActiveCfg = Release|Any CPU + {11B51A41-47CB-4EDB-9D8A-17095A65034A}.ReleaseNoBenchmarks|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -345,6 +355,7 @@ Global {8B289879-9CF1-4EFD-AD4B-781AEA94BDBE} = {8C6EFBE5-F0FB-48D1-B138-A651BB95C957} {EA847C1D-EC25-442B-A940-460969577CD5} = {C41FD56B-38CD-40E3-89E6-071A6C58E36C} {9511216F-EC10-480D-AA8D-F72312C96962} = {EA847C1D-EC25-442B-A940-460969577CD5} + {11B51A41-47CB-4EDB-9D8A-17095A65034A} = {CE6B50B2-34AE-44C9-940A-4E48C3E1B3BC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {285A5EB4-BCF4-40EB-B9E1-DF6DBCB5E705} diff --git a/samples/OracleProvider/OracleProvider.sln b/samples/OracleProvider/OracleProvider.sln index af2019a6a48..6995f3892dd 100644 --- a/samples/OracleProvider/OracleProvider.sln +++ b/samples/OracleProvider/OracleProvider.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26730.3 +VisualStudioVersion = 15.0.27004.2010 MinimumVisualStudioVersion = 15.0.26730.03 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore", "..\..\src\EFCore\EFCore.csproj", "{715C38E9-B2F5-4DB2-8025-0C6492DEBDD4}" EndProject @@ -17,6 +17,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.Relational.Specifica EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.Specification.Tests", "..\..\src\EFCore.Specification.Tests\EFCore.Specification.Tests.csproj", "{1A73D95E-E8B5-4F96-908C-7B040E4F7AFE}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EFCore.Attributes", "..\..\src\EFCore.Attributes\EFCore.Attributes.csproj", "{1561A725-B84F-4E3A-B316-1B3279DFDAF6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -47,6 +49,10 @@ Global {1A73D95E-E8B5-4F96-908C-7B040E4F7AFE}.Debug|Any CPU.Build.0 = Debug|Any CPU {1A73D95E-E8B5-4F96-908C-7B040E4F7AFE}.Release|Any CPU.ActiveCfg = Release|Any CPU {1A73D95E-E8B5-4F96-908C-7B040E4F7AFE}.Release|Any CPU.Build.0 = Release|Any CPU + {1561A725-B84F-4E3A-B316-1B3279DFDAF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1561A725-B84F-4E3A-B316-1B3279DFDAF6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1561A725-B84F-4E3A-B316-1B3279DFDAF6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1561A725-B84F-4E3A-B316-1B3279DFDAF6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -56,6 +62,7 @@ Global {6A25DF99-2615-46D8-9532-821764647EE1} = {57595541-E77D-477C-B48B-C69E061C11F9} {07FA2B15-A6A5-4292-A096-7771FB32EEDA} = {57595541-E77D-477C-B48B-C69E061C11F9} {1A73D95E-E8B5-4F96-908C-7B040E4F7AFE} = {57595541-E77D-477C-B48B-C69E061C11F9} + {1561A725-B84F-4E3A-B316-1B3279DFDAF6} = {57595541-E77D-477C-B48B-C69E061C11F9} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {321B8079-2AC6-45FF-8D19-B2550F017448} diff --git a/src/EFCore.Attributes/EFCore.Attributes.csproj b/src/EFCore.Attributes/EFCore.Attributes.csproj new file mode 100644 index 00000000000..55b9ada5a69 --- /dev/null +++ b/src/EFCore.Attributes/EFCore.Attributes.csproj @@ -0,0 +1,14 @@ + + + + Provides attributes that are used to configure Entity Framework Core + + netstandard2.0 + 3.6 + Microsoft.EntityFrameworkCore.Attributes + Microsoft.EntityFrameworkCore + true + ..\EFCore.ruleset + + + diff --git a/src/EFCore.Attributes/OwnedAttribute.cs b/src/EFCore.Attributes/OwnedAttribute.cs new file mode 100644 index 00000000000..ac63a6a2640 --- /dev/null +++ b/src/EFCore.Attributes/OwnedAttribute.cs @@ -0,0 +1,12 @@ +using System; + +namespace Microsoft.EntityFrameworkCore +{ + /// + /// Marks a type as owned. All references to this type will be configured as owned entity types. + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] + public class OwnedAttribute : Attribute + { + } +} diff --git a/src/EFCore.Specification.Tests/DataAnnotationTestBase.cs b/src/EFCore.Specification.Tests/DataAnnotationTestBase.cs index 234ff3c8281..acf19c58409 100644 --- a/src/EFCore.Specification.Tests/DataAnnotationTestBase.cs +++ b/src/EFCore.Specification.Tests/DataAnnotationTestBase.cs @@ -1793,6 +1793,7 @@ protected class Post public Author Author { get; set; } } + [ComplexType] protected class PostDetails { public int Id { get; set; } @@ -2085,7 +2086,7 @@ protected class Two public byte[] Timestamp { get; set; } } - [ComplexType] + [Owned] protected class Details { public string Name { get; set; } diff --git a/src/EFCore/EFCore.csproj b/src/EFCore/EFCore.csproj index 86a312d7d2e..5755cc66c77 100644 --- a/src/EFCore/EFCore.csproj +++ b/src/EFCore/EFCore.csproj @@ -31,6 +31,10 @@ Microsoft.EntityFrameworkCore.DbSet + + + + TextTemplatingFileGenerator diff --git a/src/EFCore/Metadata/Builders/OwnedEntityTypeBuilder.cs b/src/EFCore/Metadata/Builders/OwnedEntityTypeBuilder.cs new file mode 100644 index 00000000000..bccc850a814 --- /dev/null +++ b/src/EFCore/Metadata/Builders/OwnedEntityTypeBuilder.cs @@ -0,0 +1,42 @@ +// 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.ComponentModel; + +namespace Microsoft.EntityFrameworkCore.Metadata.Builders +{ + /// + /// + /// Instances of this class are returned from methods when using the API + /// and it is not designed to be directly constructed in your application code. + /// + /// + public class OwnedEntityTypeBuilder + { + #region Hidden System.Object members + + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. + [EditorBrowsable(EditorBrowsableState.Never)] + public override string ToString() => base.ToString(); + + /// + /// Determines whether the specified object is equal to the current object. + /// + /// The object to compare with the current object. + /// true if the specified object is equal to the current object; otherwise, false. + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => base.Equals(obj); + + /// + /// Serves as the default hash function. + /// + /// A hash code for the current object. + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => base.GetHashCode(); + + #endregion + } +} diff --git a/src/EFCore/Metadata/Builders/OwnedEntityTypeBuilder`.cs b/src/EFCore/Metadata/Builders/OwnedEntityTypeBuilder`.cs new file mode 100644 index 00000000000..b13fbfd6e7e --- /dev/null +++ b/src/EFCore/Metadata/Builders/OwnedEntityTypeBuilder`.cs @@ -0,0 +1,14 @@ +namespace Microsoft.EntityFrameworkCore.Metadata.Builders +{ + /// + /// + /// Instances of this class are returned from methods when using the API + /// and it is not designed to be directly constructed in your application code. + /// + /// + /// The entity type being configured. + // ReSharper disable once UnusedTypeParameter + public class OwnedEntityTypeBuilder : OwnedEntityTypeBuilder + { + } +} diff --git a/src/EFCore/Metadata/Conventions/Internal/OwnedEntityTypeAttributeConvention.cs b/src/EFCore/Metadata/Conventions/Internal/OwnedEntityTypeAttributeConvention.cs index 459d7d9692f..20e1227ba7f 100644 --- a/src/EFCore/Metadata/Conventions/Internal/OwnedEntityTypeAttributeConvention.cs +++ b/src/EFCore/Metadata/Conventions/Internal/OwnedEntityTypeAttributeConvention.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.ComponentModel.DataAnnotations.Schema; using Microsoft.EntityFrameworkCore.Metadata.Internal; namespace Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal @@ -10,13 +9,13 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal /// 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. /// - public class OwnedEntityTypeAttributeConvention : EntityTypeAttributeConvention + public class OwnedEntityTypeAttributeConvention : EntityTypeAttributeConvention { /// /// 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. /// - public override InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder, ComplexTypeAttribute attribute) + public override InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityTypeBuilder, OwnedAttribute attribute) => (entityTypeBuilder.Metadata.HasClrType() ? entityTypeBuilder.ModelBuilder.OwnedEntity(entityTypeBuilder.Metadata.ClrType, ConfigurationSource.DataAnnotation) : entityTypeBuilder.ModelBuilder.OwnedEntity(entityTypeBuilder.Metadata.Name, ConfigurationSource.DataAnnotation)) diff --git a/src/EFCore/ModelBuilder.cs b/src/EFCore/ModelBuilder.cs index e94d54f9000..a6d4d7af3a5 100644 --- a/src/EFCore/ModelBuilder.cs +++ b/src/EFCore/ModelBuilder.cs @@ -240,33 +240,27 @@ public virtual ModelBuilder ApplyConfiguration([NotNull] IEntityTypeCon /// Marks an entity type as owned. All references to this type will be configured as /// separate owned type instances. /// - /// The entity type to be configured. - public virtual void OwnedEntity() - where TEntity : class - => Builder.OwnedEntity(typeof(TEntity), ConfigurationSource.Explicit); + /// The entity type to be configured. + public virtual OwnedEntityTypeBuilder Owned() + where T : class + { + Builder.OwnedEntity(typeof(T), ConfigurationSource.Explicit); + + return null; + } /// /// Marks an entity type as owned. All references to this type will be configured as /// separate owned type instances. /// /// The entity type to be configured. - public virtual void OwnedEntity([NotNull] Type type) + public virtual OwnedEntityTypeBuilder Owned([NotNull] Type type) { Check.NotNull(type, nameof(type)); Builder.OwnedEntity(type, ConfigurationSource.Explicit); - } - - /// - /// Marks an entity type as owned. All references to this type will be configured as - /// separate owned type instances. - /// - /// The name of the entity type to be configured. - public virtual void OwnedEntity([NotNull] string name) - { - Check.NotEmpty(name, nameof(name)); - Builder.OwnedEntity(name, ConfigurationSource.Explicit); + return null; } /// diff --git a/test/EFCore.Tests/ApiConsistencyTest.cs b/test/EFCore.Tests/ApiConsistencyTest.cs index 292f542c878..90b637d04f6 100644 --- a/test/EFCore.Tests/ApiConsistencyTest.cs +++ b/test/EFCore.Tests/ApiConsistencyTest.cs @@ -61,7 +61,6 @@ where type.GetTypeInfo().IsVisible from method in type.GetMethods(PublicInstance) where method.DeclaringType == type && method.ReturnType == typeof(void) - && method.Name != nameof(ModelBuilder.OwnedEntity) select type.Name + "." + method.Name; Assert.Equal("", string.Join(Environment.NewLine, voidMethods)); diff --git a/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericRelationshipStringTest.cs b/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericRelationshipStringTest.cs index 5e9b583f9a9..bc7edb5e4c6 100644 --- a/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericRelationshipStringTest.cs +++ b/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericRelationshipStringTest.cs @@ -49,8 +49,8 @@ public override TestModelBuilder Entity(Action() - => ModelBuilder.OwnedEntity(); + public override void Owned() + => ModelBuilder.Owned(); public override TestModelBuilder Ignore() { diff --git a/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericRelationshipTypeStringTest.cs b/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericRelationshipTypeStringTest.cs index 982a188942a..8efec65c1b7 100644 --- a/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericRelationshipTypeStringTest.cs +++ b/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericRelationshipTypeStringTest.cs @@ -35,8 +35,8 @@ public override TestModelBuilder Entity(Action() - => ModelBuilder.OwnedEntity(); + public override void Owned() + => ModelBuilder.Owned(); public override TestModelBuilder Ignore() { diff --git a/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericRelationshipTypeTest.cs b/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericRelationshipTypeTest.cs index 994656617aa..f1af2b28cce 100644 --- a/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericRelationshipTypeTest.cs +++ b/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericRelationshipTypeTest.cs @@ -36,8 +36,8 @@ public override TestModelBuilder Entity(Action() - => ModelBuilder.OwnedEntity(); + public override void Owned() + => ModelBuilder.Owned(); public override TestModelBuilder Ignore() { diff --git a/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericTest.cs b/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericTest.cs index 7a5e388e5e1..211c5e6ea92 100644 --- a/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericTest.cs +++ b/test/EFCore.Tests/ModelBuilding/ModelBuilderGenericTest.cs @@ -123,8 +123,8 @@ public override TestModelBuilder Entity(Action() - => ModelBuilder.OwnedEntity(); + public override void Owned() + => ModelBuilder.Owned(); public override TestModelBuilder Ignore() { diff --git a/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericStringTest.cs b/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericStringTest.cs index 9328570b1dd..3a18c5018eb 100644 --- a/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericStringTest.cs +++ b/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericStringTest.cs @@ -180,11 +180,8 @@ public NonGenericStringTestEntityTypeBuilder Entity(Type type) public NonGenericStringTestEntityTypeBuilder Entity(string name) => new NonGenericStringTestEntityTypeBuilder(ModelBuilder.Entity(name)); - public override void OwnedEntity() - => ModelBuilder.OwnedEntity(typeof(TEntity)); - - public void OwnedEntity(string name) - => ModelBuilder.OwnedEntity(name); + public override void Owned() + => ModelBuilder.Owned(typeof(TEntity)); public override TestModelBuilder Ignore() { diff --git a/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericTest.cs b/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericTest.cs index 30297673eae..1f6884b92b6 100644 --- a/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericTest.cs +++ b/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericTest.cs @@ -70,8 +70,8 @@ public override TestModelBuilder Entity(Action() - => ModelBuilder.OwnedEntity(typeof(TEntity)); + public override void Owned() + => ModelBuilder.Owned(typeof(TEntity)); public override TestModelBuilder Ignore() { diff --git a/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericUnqualifiedStringTest.cs b/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericUnqualifiedStringTest.cs index c3496a46536..eed8a484091 100644 --- a/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericUnqualifiedStringTest.cs +++ b/test/EFCore.Tests/ModelBuilding/ModelBuilderNonGenericUnqualifiedStringTest.cs @@ -49,8 +49,8 @@ public override TestModelBuilder Entity(Action() - => ModelBuilder.OwnedEntity(); + public override void Owned() + => ModelBuilder.Owned(); public override TestModelBuilder Ignore() { diff --git a/test/EFCore.Tests/ModelBuilding/ModelBuilderTestBase.cs b/test/EFCore.Tests/ModelBuilding/ModelBuilderTestBase.cs index 2ac5f654efd..5f4bdb7af98 100644 --- a/test/EFCore.Tests/ModelBuilding/ModelBuilderTestBase.cs +++ b/test/EFCore.Tests/ModelBuilding/ModelBuilderTestBase.cs @@ -127,7 +127,7 @@ public abstract TestEntityTypeBuilder Entity() where TEntity : class; - public abstract void OwnedEntity() + public abstract void Owned() where TEntity : class; public abstract TestModelBuilder Entity(Action> buildAction) diff --git a/test/EFCore.Tests/ModelBuilding/OwnedTypesTestBase.cs b/test/EFCore.Tests/ModelBuilding/OwnedTypesTestBase.cs index 5d7797ab9c2..fe031f2eac2 100644 --- a/test/EFCore.Tests/ModelBuilding/OwnedTypesTestBase.cs +++ b/test/EFCore.Tests/ModelBuilding/OwnedTypesTestBase.cs @@ -214,7 +214,7 @@ public virtual void Can_configure_all_ownerships_with_one_call() { var modelBuilder = CreateModelBuilder(); - modelBuilder.OwnedEntity(); + modelBuilder.Owned(); modelBuilder.Entity().OwnsOne(b => b.Label); modelBuilder.Validate();