From 00c71db1803e151ab08681ee1a2fa66b99c993ce Mon Sep 17 00:00:00 2001 From: AndriySvyryd Date: Thu, 29 Oct 2015 16:31:23 -0700 Subject: [PATCH] Add ConventionalAnnotation to store ConfigurationSource in instead of InternalMetadataBuilder Part of #3476 --- .../EntityFramework.Core.csproj | 6 +- .../Infrastructure/Annotatable.cs | 132 ++++++++++-------- .../Infrastructure/IAnnotatable.cs | 8 +- .../DerivedTypeDiscoveryConvention.cs | 3 +- .../Metadata/IMutableAnnotatable.cs | 13 +- .../Metadata/IMutableForeignKey.cs | 5 +- .../Metadata/IMutableModel.cs | 2 +- .../Internal/ConventionalAnnotatable.cs | 38 +++++ .../Internal/ConventionalAnnotation.cs | 24 ++++ .../Metadata/Internal/EntityType.cs | 3 +- .../Metadata/Internal/ForeignKey.cs | 3 +- .../Metadata/Internal/Index.cs | 3 +- .../Internal/InternalMetadataBuilder.cs | 46 ++---- .../Internal/InternalMetadataBuilder`.cs | 3 +- .../Internal/InternalMetadataItemBuilder.cs | 3 +- .../Metadata/Internal/Key.cs | 3 +- .../Metadata/Internal/Model.cs | 44 ++---- .../Metadata/Internal/Navigation.cs | 3 +- .../Metadata/Internal/Property.cs | 3 +- .../Metadata/RelationalAnnotations.cs | 2 +- .../Internal/MigrationsModelDiffer.cs | 2 +- .../Internal/InternalMetadataBuilderTest.cs | 8 +- .../Internal/InternalModelBuilderTest.cs | 4 +- .../EntityTypeAttributeConventionTest.cs | 9 +- .../RelationshipDiscoveryConventionTest.cs | 70 +++++----- .../NonRelationshipTestBase.cs | 8 +- 26 files changed, 244 insertions(+), 204 deletions(-) create mode 100644 src/EntityFramework.Core/Metadata/Internal/ConventionalAnnotatable.cs create mode 100644 src/EntityFramework.Core/Metadata/Internal/ConventionalAnnotation.cs diff --git a/src/EntityFramework.Core/EntityFramework.Core.csproj b/src/EntityFramework.Core/EntityFramework.Core.csproj index 8a9a5dc0ce2..141ae504a5f 100644 --- a/src/EntityFramework.Core/EntityFramework.Core.csproj +++ b/src/EntityFramework.Core/EntityFramework.Core.csproj @@ -29,7 +29,7 @@ pdbonly true bin\Release\ - TRACE;CSPROJ + TRACE;CSPROJ;NET451 prompt 4 true @@ -86,6 +86,8 @@ + + @@ -492,4 +494,4 @@ --> - + \ No newline at end of file diff --git a/src/EntityFramework.Core/Infrastructure/Annotatable.cs b/src/EntityFramework.Core/Infrastructure/Annotatable.cs index 98e0a35f13b..e2f58986890 100644 --- a/src/EntityFramework.Core/Infrastructure/Annotatable.cs +++ b/src/EntityFramework.Core/Infrastructure/Annotatable.cs @@ -3,79 +3,96 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; +using System.Linq; using JetBrains.Annotations; using Microsoft.Data.Entity.Internal; +using Microsoft.Data.Entity.Metadata; using Microsoft.Data.Entity.Utilities; namespace Microsoft.Data.Entity.Infrastructure { /// /// - /// Base class for types that support reading and writing annotations. + /// Base class for types that support reading and writing annotations. /// /// /// This type is typically used by database providers (and other extensions). It is generally /// not used in application code. /// /// - public class Annotatable : IAnnotatable + public class Annotatable : IMutableAnnotatable { - // TODO: Perf: use a mutable structure before the model is made readonly - // Issue #868 - private readonly LazyRef> _annotations - = new LazyRef>( - () => ImmutableSortedSet.Empty.WithComparer(new AnnotationComparer())); + private readonly LazyRef> _annotations = + new LazyRef>(() => new SortedDictionary()); + + /// + /// Gets all annotations on the current object. + /// + public virtual IEnumerable GetAnnotations() => + _annotations.HasValue + ? _annotations.Value.Values + : Enumerable.Empty(); /// /// Adds an annotation to this object. Throws if an annotation with the specified name already exists. /// - /// The key of the annotation to be added. + /// The key of the annotation to be added. /// The value to be stored in the annotation. /// The newly added annotation. - public virtual Annotation AddAnnotation([NotNull] string annotationName, [NotNull] object value) + public virtual Annotation AddAnnotation(string name, object value) { - Check.NotEmpty(annotationName, nameof(annotationName)); + Check.NotEmpty(name, nameof(name)); Check.NotNull(value, nameof(value)); - var annotation = new Annotation(annotationName, value); + var annotation = CreateAnnotation(name, value); + + return AddAnnotation(name, annotation); + } + protected virtual Annotation AddAnnotation(string name, Annotation annotation) + { var previousLength = _annotations.Value.Count; - _annotations.Value = _annotations.Value.Add(annotation); + _annotations.Value[name] = annotation; if (previousLength == _annotations.Value.Count) { - throw new InvalidOperationException(CoreStrings.DuplicateAnnotation(annotationName)); + throw new InvalidOperationException(CoreStrings.DuplicateAnnotation(name)); } return annotation; } /// - /// Adds an annotation to this object or returns the existing annotation if one with the specified name already exists. + /// Adds an annotation to this object or returns the existing annotation if one with the specified name + /// already exists. /// - /// The key of the annotation to be added. + /// The key of the annotation to be added. /// The value to be stored in the annotation. - /// - /// The existing annotation if an annotation with the specified name already exists. Otherwise, the newly added annotation. + /// + /// The existing annotation if an annotation with the specified name already exists. Otherwise, the newly + /// added annotation. /// - public virtual Annotation GetOrAddAnnotation([NotNull] string annotationName, [NotNull] object value) - => FindAnnotation(annotationName) ?? AddAnnotation(annotationName, value); + public virtual Annotation GetOrAddAnnotation([NotNull] string name, [NotNull] object value) + => FindAnnotation(name) ?? AddAnnotation(name, value); /// /// Gets the annotation with the given name, returning null if it does not exist. /// - /// The key of the annotation to find. + /// The key of the annotation to find. /// - /// The existing annotation if an annotation with the specified name already exists. Otherwise, null. + /// The existing annotation if an annotation with the specified name already exists. Otherwise, null. /// - public virtual Annotation FindAnnotation([NotNull] string annotationName) + public virtual Annotation FindAnnotation(string name) { - Check.NotEmpty(annotationName, nameof(annotationName)); + Check.NotEmpty(name, nameof(name)); + + if (!_annotations.HasValue) + { + return null; + } Annotation annotation; - return _annotations.HasValue - && _annotations.Value.TryGetValue(new Annotation(annotationName, "_"), out annotation) + return _annotations.Value.TryGetValue(name, out annotation) ? annotation : null; } @@ -83,63 +100,54 @@ public virtual Annotation FindAnnotation([NotNull] string annotationName) /// /// Removes the given annotation from this object. /// - /// The annotation to remove. + /// The annotation to remove. /// The annotation that was removed. - public virtual Annotation RemoveAnnotation([NotNull] string annotationName) + public virtual Annotation RemoveAnnotation(string name) { - Check.NotNull(annotationName, nameof(annotationName)); - - var previousAnnotations = _annotations.Value; - var annotation = new Annotation(annotationName, "_"); - _annotations.Value = _annotations.Value.Remove(annotation); + Check.NotNull(name, nameof(name)); - Annotation removedAnnotations = null; - if (previousAnnotations.Count != _annotations.Value.Count) + var annotation = FindAnnotation(name); + if (annotation == null) { - previousAnnotations.TryGetValue(annotation, out removedAnnotations); + return null; } - return removedAnnotations; + _annotations.Value.Remove(name); + + return annotation; } /// /// Gets the value annotation with the given name, returning null if it does not exist. /// - /// The key of the annotation to find. - /// - /// The value of the existing annotation if an annotation with the specified name already exists. Otherwise, null. + /// The key of the annotation to find. + /// + /// The value of the existing annotation if an annotation with the specified name already exists. + /// Otherwise, null. /// // ReSharper disable once AnnotationRedundancyInHierarchy // TODO: Fix API test to handle indexer - public virtual object this[[NotNull] string annotationName] + public virtual object this[[NotNull] string name] { - get { return FindAnnotation(annotationName)?.Value; } + get { return FindAnnotation(name)?.Value; } [param: CanBeNull] set { - Check.NotEmpty(annotationName, nameof(annotationName)); + Check.NotEmpty(name, nameof(name)); - _annotations.Value = _annotations.Value.Remove(new Annotation(annotationName, "_")); - - if (value != null) + if (value == null) + { + RemoveAnnotation(name); + } + else { - AddAnnotation(annotationName, value); + _annotations.Value[name] = CreateAnnotation(name, value); } } } - /// - /// Gets all annotations on the current object. - /// - public virtual IEnumerable GetAnnotations() - => _annotations.HasValue - ? (IEnumerable)_annotations.Value - : ImmutableList.Empty; - - private class AnnotationComparer : IComparer - { - public int Compare(IAnnotation x, IAnnotation y) => StringComparer.Ordinal.Compare(x.Name, y.Name); - } + protected virtual Annotation CreateAnnotation([NotNull] string name, [NotNull] object value) + => new Annotation(name, value); /// /// Gets all annotations on the current object. @@ -149,10 +157,10 @@ private class AnnotationComparer : IComparer /// /// Gets the annotation with the given name, returning null if it does not exist. /// - /// The key of the annotation to find. + /// The key of the annotation to find. /// - /// The existing annotation if an annotation with the specified name already exists. Otherwise, null. + /// The existing annotation if an annotation with the specified name already exists. Otherwise, null. /// - IAnnotation IAnnotatable.FindAnnotation(string annotationName) => FindAnnotation(annotationName); + IAnnotation IAnnotatable.FindAnnotation(string name) => FindAnnotation(name); } } diff --git a/src/EntityFramework.Core/Infrastructure/IAnnotatable.cs b/src/EntityFramework.Core/Infrastructure/IAnnotatable.cs index 9465c505020..3c59c95352c 100644 --- a/src/EntityFramework.Core/Infrastructure/IAnnotatable.cs +++ b/src/EntityFramework.Core/Infrastructure/IAnnotatable.cs @@ -20,22 +20,22 @@ public interface IAnnotatable /// /// Gets the value annotation with the given name, returning null if it does not exist. /// - /// The key of the annotation to find. + /// The key of the annotation to find. /// /// The value of the existing annotation if an annotation with the specified name already exists. Otherwise, null. /// // ReSharper disable once AnnotationRedundancyInHierarchy // TODO: Fix API test to handle indexer - object this[[NotNull] string annotationName] { get; } + object this[[NotNull] string name] { get; } /// /// Gets the annotation with the given name, returning null if it does not exist. /// - /// The key of the annotation to find. + /// The key of the annotation to find. /// /// The existing annotation if an annotation with the specified name already exists. Otherwise, null. /// - IAnnotation FindAnnotation([NotNull] string annotationName); + IAnnotation FindAnnotation([NotNull] string name); /// /// Gets all annotations on the current object. diff --git a/src/EntityFramework.Core/Metadata/Conventions/Internal/DerivedTypeDiscoveryConvention.cs b/src/EntityFramework.Core/Metadata/Conventions/Internal/DerivedTypeDiscoveryConvention.cs index 8f1e0e98a4e..21c5f086f94 100644 --- a/src/EntityFramework.Core/Metadata/Conventions/Internal/DerivedTypeDiscoveryConvention.cs +++ b/src/EntityFramework.Core/Metadata/Conventions/Internal/DerivedTypeDiscoveryConvention.cs @@ -20,7 +20,8 @@ public virtual InternalEntityTypeBuilder Apply(InternalEntityTypeBuilder entityT var directlyDerivedTypes = entityType.Model.GetEntityTypes().Where(t => t.BaseType == entityType.BaseType && t.HasClrType() - && FindClosestBaseType(t) == entityType); + && FindClosestBaseType(t) == entityType) + .ToList(); foreach (var directlyDerivedType in directlyDerivedTypes) { diff --git a/src/EntityFramework.Core/Metadata/IMutableAnnotatable.cs b/src/EntityFramework.Core/Metadata/IMutableAnnotatable.cs index 8a0cd1c99e3..46ba1e1ccfb 100644 --- a/src/EntityFramework.Core/Metadata/IMutableAnnotatable.cs +++ b/src/EntityFramework.Core/Metadata/IMutableAnnotatable.cs @@ -1,3 +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.Collections.Generic; using JetBrains.Annotations; using Microsoft.Data.Entity.Infrastructure; @@ -6,10 +9,10 @@ namespace Microsoft.Data.Entity.Metadata { public interface IMutableAnnotatable : IAnnotatable { - new object this[[NotNull] string annotationName] { get; [param: CanBeNull] set; } + new object this[[NotNull] string name] { get; [param: CanBeNull] set; } new IEnumerable GetAnnotations(); - Annotation AddAnnotation([NotNull] string annotationName, [NotNull] object value); - new Annotation FindAnnotation([NotNull] string annotationName); - Annotation RemoveAnnotation([NotNull] string annotationName); + Annotation AddAnnotation([NotNull] string name, [NotNull] object value); + new Annotation FindAnnotation([NotNull] string name); + Annotation RemoveAnnotation([NotNull] string name); } -} \ No newline at end of file +} diff --git a/src/EntityFramework.Core/Metadata/IMutableForeignKey.cs b/src/EntityFramework.Core/Metadata/IMutableForeignKey.cs index 163010a2ef8..ee0bb27ed2e 100644 --- a/src/EntityFramework.Core/Metadata/IMutableForeignKey.cs +++ b/src/EntityFramework.Core/Metadata/IMutableForeignKey.cs @@ -1,3 +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.Collections.Generic; using JetBrains.Annotations; @@ -17,4 +20,4 @@ public interface IMutableForeignKey : IForeignKey, IMutableAnnotatable new bool? IsRequired { get; set; } new DeleteBehavior? DeleteBehavior { get; set; } } -} \ No newline at end of file +} diff --git a/src/EntityFramework.Core/Metadata/IMutableModel.cs b/src/EntityFramework.Core/Metadata/IMutableModel.cs index 6acd34e3174..d130edbb750 100644 --- a/src/EntityFramework.Core/Metadata/IMutableModel.cs +++ b/src/EntityFramework.Core/Metadata/IMutableModel.cs @@ -11,6 +11,6 @@ public interface IMutableModel : IModel, IMutableAnnotatable IMutableEntityType AddEntityType([NotNull] string name); new IMutableEntityType FindEntityType([NotNull] string name); IMutableEntityType RemoveEntityType([NotNull] string name); - new IReadOnlyList GetEntityTypes(); + new IEnumerable GetEntityTypes(); } } diff --git a/src/EntityFramework.Core/Metadata/Internal/ConventionalAnnotatable.cs b/src/EntityFramework.Core/Metadata/Internal/ConventionalAnnotatable.cs new file mode 100644 index 00000000000..5053e0470fb --- /dev/null +++ b/src/EntityFramework.Core/Metadata/Internal/ConventionalAnnotatable.cs @@ -0,0 +1,38 @@ +// 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.Collections.Generic; +using System.Linq; +using JetBrains.Annotations; +using Microsoft.Data.Entity.Infrastructure; + +namespace Microsoft.Data.Entity.Metadata.Internal +{ + public class ConventionalAnnotatable : Annotatable + { + public new virtual IEnumerable GetAnnotations() => base.GetAnnotations().Cast(); + + public virtual ConventionalAnnotation AddAnnotation( + [NotNull] string name, [NotNull] object value, ConfigurationSource configurationSource) + => (ConventionalAnnotation)base.AddAnnotation(name, CreateAnnotation(name, value, configurationSource)); + + public new virtual ConventionalAnnotation AddAnnotation([NotNull] string name, [NotNull] object value) + => (ConventionalAnnotation)base.AddAnnotation(name, value); + + public new virtual ConventionalAnnotation GetOrAddAnnotation([NotNull] string name, [NotNull] object value) + => (ConventionalAnnotation)base.GetOrAddAnnotation(name, value); + + public new virtual ConventionalAnnotation FindAnnotation([NotNull] string name) + => (ConventionalAnnotation)base.FindAnnotation(name); + + public new virtual ConventionalAnnotation RemoveAnnotation([NotNull] string name) + => (ConventionalAnnotation)base.RemoveAnnotation(name); + + private ConventionalAnnotation CreateAnnotation( + string name, object value, ConfigurationSource configurationSource) + => new ConventionalAnnotation(name, value, configurationSource); + + protected override Annotation CreateAnnotation(string name, object value) + => CreateAnnotation(name, value, ConfigurationSource.Explicit); + } +} diff --git a/src/EntityFramework.Core/Metadata/Internal/ConventionalAnnotation.cs b/src/EntityFramework.Core/Metadata/Internal/ConventionalAnnotation.cs new file mode 100644 index 00000000000..dd71e02129d --- /dev/null +++ b/src/EntityFramework.Core/Metadata/Internal/ConventionalAnnotation.cs @@ -0,0 +1,24 @@ +// 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.Data.Entity.Infrastructure; + +namespace Microsoft.Data.Entity.Metadata.Internal +{ + public class ConventionalAnnotation : Annotation + { + private ConfigurationSource _configurationSource; + + public ConventionalAnnotation([NotNull] string name, [NotNull] object value, ConfigurationSource configurationSource) + : base(name, value) + { + _configurationSource = configurationSource; + } + + public ConfigurationSource GetConfigurationSource() => _configurationSource; + + public ConfigurationSource UpdateConfigurationSource(ConfigurationSource configurationSource) + => _configurationSource = _configurationSource.Max(configurationSource); + } +} diff --git a/src/EntityFramework.Core/Metadata/Internal/EntityType.cs b/src/EntityFramework.Core/Metadata/Internal/EntityType.cs index d30c8f7e36c..0544771e49d 100644 --- a/src/EntityFramework.Core/Metadata/Internal/EntityType.cs +++ b/src/EntityFramework.Core/Metadata/Internal/EntityType.cs @@ -7,13 +7,12 @@ using System.Linq; using System.Reflection; using JetBrains.Annotations; -using Microsoft.Data.Entity.Infrastructure; using Microsoft.Data.Entity.Internal; using Microsoft.Data.Entity.Utilities; namespace Microsoft.Data.Entity.Metadata.Internal { - public class EntityType : Annotatable, IMutableEntityType, ICanGetNavigations + public class EntityType : ConventionalAnnotatable, IMutableEntityType, ICanGetNavigations { private static readonly char[] _simpleNameChars = { '.', '+' }; diff --git a/src/EntityFramework.Core/Metadata/Internal/ForeignKey.cs b/src/EntityFramework.Core/Metadata/Internal/ForeignKey.cs index c0db7c5c5f9..c1e1cd8673e 100644 --- a/src/EntityFramework.Core/Metadata/Internal/ForeignKey.cs +++ b/src/EntityFramework.Core/Metadata/Internal/ForeignKey.cs @@ -5,13 +5,12 @@ using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; -using Microsoft.Data.Entity.Infrastructure; using Microsoft.Data.Entity.Internal; using Microsoft.Data.Entity.Utilities; namespace Microsoft.Data.Entity.Metadata.Internal { - public class ForeignKey : Annotatable, IMutableForeignKey + public class ForeignKey : ConventionalAnnotatable, IMutableForeignKey { private DeleteBehavior? _deleteBehavior; diff --git a/src/EntityFramework.Core/Metadata/Internal/Index.cs b/src/EntityFramework.Core/Metadata/Internal/Index.cs index 4ffa5559d9d..9c2577a83a1 100644 --- a/src/EntityFramework.Core/Metadata/Internal/Index.cs +++ b/src/EntityFramework.Core/Metadata/Internal/Index.cs @@ -4,13 +4,12 @@ using System.Collections.Generic; using System.Diagnostics; using JetBrains.Annotations; -using Microsoft.Data.Entity.Infrastructure; using Microsoft.Data.Entity.Utilities; namespace Microsoft.Data.Entity.Metadata.Internal { [DebuggerDisplay("{DebuggerDisplay,nq}")] - public class Index : Annotatable, IMutableIndex + public class Index : ConventionalAnnotatable, IMutableIndex { public Index([NotNull] IReadOnlyList properties) { diff --git a/src/EntityFramework.Core/Metadata/Internal/InternalMetadataBuilder.cs b/src/EntityFramework.Core/Metadata/Internal/InternalMetadataBuilder.cs index 741198885a4..e30d986fa79 100644 --- a/src/EntityFramework.Core/Metadata/Internal/InternalMetadataBuilder.cs +++ b/src/EntityFramework.Core/Metadata/Internal/InternalMetadataBuilder.cs @@ -1,24 +1,19 @@ // 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.Collections.Generic; +using System.Diagnostics; using JetBrains.Annotations; -using Microsoft.Data.Entity.Infrastructure; -using Microsoft.Data.Entity.Internal; namespace Microsoft.Data.Entity.Metadata.Internal { public abstract class InternalMetadataBuilder { - private readonly LazyRef> _annotationSources = - new LazyRef>(() => new Dictionary()); - - protected InternalMetadataBuilder([NotNull] Annotatable metadata) + protected InternalMetadataBuilder([NotNull] ConventionalAnnotatable metadata) { Metadata = metadata; } - public virtual Annotatable Metadata { get; } + public virtual ConventionalAnnotatable Metadata { get; } public abstract InternalModelBuilder ModelBuilder { get; } public virtual bool HasAnnotation( @@ -28,34 +23,29 @@ public virtual bool HasAnnotation( private bool HasAnnotation( string name, object value, ConfigurationSource configurationSource, bool canOverrideSameSource) { - var existingValue = Metadata[name]; - if (existingValue != null) + var existingAnnotation = Metadata.FindAnnotation(name); + if (existingAnnotation != null) { - ConfigurationSource existingConfigurationSource; - if (!_annotationSources.Value.TryGetValue(name, out existingConfigurationSource)) + if (existingAnnotation.Value.Equals(value)) { - existingConfigurationSource = ConfigurationSource.Explicit; + existingAnnotation.UpdateConfigurationSource(configurationSource); + return true; } - if ((value == null || !existingValue.Equals(value)) - && (!configurationSource.Overrides(existingConfigurationSource) - || configurationSource == existingConfigurationSource && !canOverrideSameSource)) + var existingConfigurationSource = existingAnnotation.GetConfigurationSource(); + if ((!configurationSource.Overrides(existingConfigurationSource) + || configurationSource == existingConfigurationSource && !canOverrideSameSource)) { return false; } - configurationSource = configurationSource.Max(existingConfigurationSource); + var removed = Metadata.RemoveAnnotation(name); + Debug.Assert(removed == existingAnnotation); } if (value != null) { - _annotationSources.Value[name] = configurationSource; - Metadata[name] = value; - } - else - { - _annotationSources.Value.Remove(name); - Metadata.RemoveAnnotation(name); + Metadata.AddAnnotation(name, value, configurationSource); } return true; @@ -65,16 +55,10 @@ protected virtual void MergeAnnotationsFrom([NotNull] InternalMetadataBuilder an { foreach (var annotation in annotatableBuilder.Metadata.GetAnnotations()) { - ConfigurationSource annotationSource; - if (!annotatableBuilder._annotationSources.Value.TryGetValue(annotation.Name, out annotationSource)) - { - annotationSource = ConfigurationSource.Explicit; - } - HasAnnotation( annotation.Name, annotation.Value, - annotationSource, + annotation.GetConfigurationSource(), canOverrideSameSource: false); } } diff --git a/src/EntityFramework.Core/Metadata/Internal/InternalMetadataBuilder`.cs b/src/EntityFramework.Core/Metadata/Internal/InternalMetadataBuilder`.cs index 235643cfd64..0f802be01b7 100644 --- a/src/EntityFramework.Core/Metadata/Internal/InternalMetadataBuilder`.cs +++ b/src/EntityFramework.Core/Metadata/Internal/InternalMetadataBuilder`.cs @@ -2,12 +2,11 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using JetBrains.Annotations; -using Microsoft.Data.Entity.Infrastructure; namespace Microsoft.Data.Entity.Metadata.Internal { public abstract class InternalMetadataBuilder : InternalMetadataBuilder - where TMetadata : Annotatable + where TMetadata : ConventionalAnnotatable { protected InternalMetadataBuilder([NotNull] TMetadata metadata) : base(metadata) diff --git a/src/EntityFramework.Core/Metadata/Internal/InternalMetadataItemBuilder.cs b/src/EntityFramework.Core/Metadata/Internal/InternalMetadataItemBuilder.cs index b4bd65e32e8..958e36281d0 100644 --- a/src/EntityFramework.Core/Metadata/Internal/InternalMetadataItemBuilder.cs +++ b/src/EntityFramework.Core/Metadata/Internal/InternalMetadataItemBuilder.cs @@ -2,12 +2,11 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using JetBrains.Annotations; -using Microsoft.Data.Entity.Infrastructure; namespace Microsoft.Data.Entity.Metadata.Internal { public abstract class InternalMetadataItemBuilder : InternalMetadataBuilder - where TMetadata : Annotatable + where TMetadata : ConventionalAnnotatable { protected InternalMetadataItemBuilder([NotNull] TMetadata metadata, [NotNull] InternalModelBuilder modelBuilder) : base(metadata) diff --git a/src/EntityFramework.Core/Metadata/Internal/Key.cs b/src/EntityFramework.Core/Metadata/Internal/Key.cs index 50e0221309b..ee5748cf838 100644 --- a/src/EntityFramework.Core/Metadata/Internal/Key.cs +++ b/src/EntityFramework.Core/Metadata/Internal/Key.cs @@ -5,13 +5,12 @@ using System.Diagnostics; using System.Linq; using JetBrains.Annotations; -using Microsoft.Data.Entity.Infrastructure; using Microsoft.Data.Entity.Utilities; namespace Microsoft.Data.Entity.Metadata.Internal { [DebuggerDisplay("{DebuggerDisplay,nq}")] - public class Key : Annotatable, IMutableKey + public class Key : ConventionalAnnotatable, IMutableKey { public Key([NotNull] IReadOnlyList properties) { diff --git a/src/EntityFramework.Core/Metadata/Internal/Model.cs b/src/EntityFramework.Core/Metadata/Internal/Model.cs index 4eebcaaedb8..535a4790e83 100644 --- a/src/EntityFramework.Core/Metadata/Internal/Model.cs +++ b/src/EntityFramework.Core/Metadata/Internal/Model.cs @@ -3,33 +3,25 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; +using System.Diagnostics; using System.Linq; using JetBrains.Annotations; -using Microsoft.Data.Entity.Infrastructure; using Microsoft.Data.Entity.Internal; using Microsoft.Data.Entity.Utilities; namespace Microsoft.Data.Entity.Metadata.Internal { - public class Model : Annotatable, IMutableModel + public class Model : ConventionalAnnotatable, IMutableModel { - private ImmutableSortedSet _entities - = ImmutableSortedSet.Empty.WithComparer(new EntityTypeNameComparer()); + private readonly SortedDictionary _entities = new SortedDictionary(); public virtual EntityType AddEntityType([NotNull] string name) { Check.NotEmpty(name, nameof(name)); - return AddEntityType(new EntityType(name, this)); - } - - public virtual EntityType AddEntityType([NotNull] Type type) => (EntityType)((IMutableModel)this).AddEntityType(type); - - private EntityType AddEntityType(EntityType entityType) - { + var entityType = new EntityType(name, this); var previousLength = _entities.Count; - _entities = _entities.Add(entityType); + _entities[name] = entityType; if (previousLength == _entities.Count) { @@ -39,6 +31,8 @@ private EntityType AddEntityType(EntityType entityType) return entityType; } + public virtual EntityType AddEntityType([NotNull] Type type) => (EntityType)((IMutableModel)this).AddEntityType(type); + public virtual EntityType GetOrAddEntityType([NotNull] Type type) => FindEntityType(type) ?? AddEntityType(type); @@ -52,13 +46,11 @@ public virtual EntityType FindEntityType([NotNull] string name) { Check.NotEmpty(name, nameof(name)); - return FindEntityType(new EntityType(name, this)); - } - - private EntityType FindEntityType(EntityType entityType) - => _entities.TryGetValue(entityType, out entityType) + EntityType entityType; + return _entities.TryGetValue(name, out entityType) ? entityType : null; + } public virtual EntityType RemoveEntityType([NotNull] Type type) { @@ -99,25 +91,19 @@ private EntityType RemoveEntityType([NotNull] EntityType entityType) derivedEntityType.DisplayName())); } - var previousEntities = _entities; - _entities = _entities.Remove(entityType); + var removed = _entities.Remove(entityType.Name); + Debug.Assert(removed); - EntityType removedEntityType = null; - if (previousEntities.Count != _entities.Count) - { - previousEntities.TryGetValue(entityType, out removedEntityType); - } - - return removedEntityType; + return entityType; } - public virtual IReadOnlyList GetEntityTypes() => _entities; + public virtual IEnumerable GetEntityTypes() => _entities.Values; IEntityType IModel.FindEntityType(string name) => FindEntityType(name); IEnumerable IModel.GetEntityTypes() => GetEntityTypes(); IMutableEntityType IMutableModel.AddEntityType(string name) => AddEntityType(name); - IReadOnlyList IMutableModel.GetEntityTypes() => GetEntityTypes(); + IEnumerable IMutableModel.GetEntityTypes() => GetEntityTypes(); IMutableEntityType IMutableModel.FindEntityType(string name) => FindEntityType(name); IMutableEntityType IMutableModel.RemoveEntityType(string name) => RemoveEntityType(name); } diff --git a/src/EntityFramework.Core/Metadata/Internal/Navigation.cs b/src/EntityFramework.Core/Metadata/Internal/Navigation.cs index 02a63ddd3b0..fd5ff56a021 100644 --- a/src/EntityFramework.Core/Metadata/Internal/Navigation.cs +++ b/src/EntityFramework.Core/Metadata/Internal/Navigation.cs @@ -7,14 +7,13 @@ using System.Reflection; using System.Threading; using JetBrains.Annotations; -using Microsoft.Data.Entity.Infrastructure; using Microsoft.Data.Entity.Internal; using Microsoft.Data.Entity.Utilities; namespace Microsoft.Data.Entity.Metadata.Internal { [DebuggerDisplay("{DeclaringEntityType.Name,nq}.{Name,nq}")] - public class Navigation : Annotatable, IMutableNavigation, INavigationAccessors + public class Navigation : ConventionalAnnotatable, IMutableNavigation, INavigationAccessors { // Warning: Never access this field directly as access needs to be thread-safe private IClrPropertyGetter _getter; diff --git a/src/EntityFramework.Core/Metadata/Internal/Property.cs b/src/EntityFramework.Core/Metadata/Internal/Property.cs index e3a22f564f7..3eed6fbd470 100644 --- a/src/EntityFramework.Core/Metadata/Internal/Property.cs +++ b/src/EntityFramework.Core/Metadata/Internal/Property.cs @@ -8,14 +8,13 @@ using System.Reflection; using System.Threading; using JetBrains.Annotations; -using Microsoft.Data.Entity.Infrastructure; using Microsoft.Data.Entity.Internal; using Microsoft.Data.Entity.Utilities; namespace Microsoft.Data.Entity.Metadata.Internal { [DebuggerDisplay("{DeclaringEntityType.Name,nq}.{Name,nq} ({ClrType?.Name,nq})")] - public class Property : Annotatable, IMutableProperty, IPropertyBaseAccessors + public class Property : ConventionalAnnotatable, IMutableProperty, IPropertyBaseAccessors { // Warning: Never access this field directly as access needs to be thread-safe private IClrPropertyGetter _getter; diff --git a/src/EntityFramework.Relational/Metadata/RelationalAnnotations.cs b/src/EntityFramework.Relational/Metadata/RelationalAnnotations.cs index c1f2f399221..0c70a0bd46b 100644 --- a/src/EntityFramework.Relational/Metadata/RelationalAnnotations.cs +++ b/src/EntityFramework.Relational/Metadata/RelationalAnnotations.cs @@ -38,7 +38,7 @@ public virtual bool SetAnnotation([NotNull] string annotationName, [CanBeNull] o { Check.NotEmpty(annotationName, nameof(annotationName)); - var annotatable = Metadata as Annotatable; + var annotatable = Metadata as IMutableAnnotatable; Debug.Assert(annotatable != null); var fullName = (ProviderPrefix ?? RelationalAnnotationNames.Prefix) + annotationName; diff --git a/src/EntityFramework.Relational/Migrations/Internal/MigrationsModelDiffer.cs b/src/EntityFramework.Relational/Migrations/Internal/MigrationsModelDiffer.cs index 10d10b3f936..c3a7c01f68d 100644 --- a/src/EntityFramework.Relational/Migrations/Internal/MigrationsModelDiffer.cs +++ b/src/EntityFramework.Relational/Migrations/Internal/MigrationsModelDiffer.cs @@ -882,7 +882,7 @@ protected virtual bool HasDifferences([NotNull] IEnumerable source, return unmatched.Count != 0; } - protected virtual void CopyAnnotations([NotNull] IEnumerable annotations, [NotNull] Annotatable annotatable) + protected virtual void CopyAnnotations([NotNull] IEnumerable annotations, [NotNull] IMutableAnnotatable annotatable) { foreach (var annotation in annotations) { diff --git a/test/EntityFramework.Core.Tests/Metadata/Internal/InternalMetadataBuilderTest.cs b/test/EntityFramework.Core.Tests/Metadata/Internal/InternalMetadataBuilderTest.cs index 07ad14f52a2..955a3c26d0f 100644 --- a/test/EntityFramework.Core.Tests/Metadata/Internal/InternalMetadataBuilderTest.cs +++ b/test/EntityFramework.Core.Tests/Metadata/Internal/InternalMetadataBuilderTest.cs @@ -9,11 +9,6 @@ namespace Microsoft.Data.Entity.Metadata.Internal { public class InternalMetadataBuilderTest { - private InternalMetadataBuilder CreateInternalMetadataBuilder() - { - return new InternalModelBuilder(new Model(), new ConventionSet()); - } - [Fact] public void Can_only_override_lower_source_annotation() { @@ -59,5 +54,8 @@ public void Annotation_set_explicitly_can_not_be_removed_by_convention() Assert.True(builder.HasAnnotation("Foo", null, ConfigurationSource.Explicit)); Assert.Equal(0, metadata.GetAnnotations().Count()); } + + private InternalMetadataBuilder CreateInternalMetadataBuilder() + => new InternalModelBuilder(new Model(), new ConventionSet()); } } diff --git a/test/EntityFramework.Core.Tests/Metadata/Internal/InternalModelBuilderTest.cs b/test/EntityFramework.Core.Tests/Metadata/Internal/InternalModelBuilderTest.cs index 33925b6329d..1e80b3ee625 100644 --- a/test/EntityFramework.Core.Tests/Metadata/Internal/InternalModelBuilderTest.cs +++ b/test/EntityFramework.Core.Tests/Metadata/Internal/InternalModelBuilderTest.cs @@ -166,7 +166,7 @@ public void Can_ignore_entity_type_with_base_and_derived_types() Assert.True(modelBuilder.Ignore(typeof(Customer), ConfigurationSource.DataAnnotation)); - Assert.Equal(2, modelBuilder.Metadata.GetEntityTypes().Count); + Assert.Equal(2, modelBuilder.Metadata.GetEntityTypes().Count()); Assert.Same(baseEntityTypeBuilder.Metadata, specialCustomerEntityTypeBuilder.Metadata.BaseType); } @@ -183,7 +183,7 @@ public void Cannot_ignore_entity_type_referenced_from_higher_source_foreign_key( Assert.False(modelBuilder.Ignore(typeof(Customer), ConfigurationSource.DataAnnotation)); - Assert.Equal(2, modelBuilder.Metadata.GetEntityTypes().Count); + Assert.Equal(2, modelBuilder.Metadata.GetEntityTypes().Count()); Assert.Equal(1, orderEntityTypeBuilder.Metadata.GetForeignKeys().Count()); } diff --git a/test/EntityFramework.Core.Tests/Metadata/ModelConventions/EntityTypeAttributeConventionTest.cs b/test/EntityFramework.Core.Tests/Metadata/ModelConventions/EntityTypeAttributeConventionTest.cs index 30ffcb703f8..a1d1a49d793 100644 --- a/test/EntityFramework.Core.Tests/Metadata/ModelConventions/EntityTypeAttributeConventionTest.cs +++ b/test/EntityFramework.Core.Tests/Metadata/ModelConventions/EntityTypeAttributeConventionTest.cs @@ -1,7 +1,8 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// 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 System.Linq; using Microsoft.Data.Entity.Metadata.Conventions.Internal; using Microsoft.Data.Entity.Metadata.Internal; using Xunit; @@ -21,7 +22,7 @@ public void NotMappedAttribute_overrides_configuration_from_convention_source() new NotMappedEntityTypeAttributeConvention().Apply(entityBuilder); - Assert.Equal(0, modelBuilder.Metadata.GetEntityTypes().Count); + Assert.Equal(0, modelBuilder.Metadata.GetEntityTypes().Count()); } [Fact] @@ -33,7 +34,7 @@ public void NotMappedAttribute_does_not_override_configuration_from_explicit_sou new NotMappedEntityTypeAttributeConvention().Apply(entityBuilder); - Assert.Equal(1, modelBuilder.Metadata.GetEntityTypes().Count); + Assert.Equal(1, modelBuilder.Metadata.GetEntityTypes().Count()); } [Fact] @@ -42,7 +43,7 @@ public void NotMappedAttribute_ignores_entityTypes_with_conventional_builder() var modelBuilder = new ModelBuilder(new CoreConventionSetBuilder().CreateConventionSet()); modelBuilder.Entity(); - Assert.Equal(1, modelBuilder.Model.GetEntityTypes().Count); + Assert.Equal(1, modelBuilder.Model.GetEntityTypes().Count()); } #endregion diff --git a/test/EntityFramework.Core.Tests/Metadata/ModelConventions/RelationshipDiscoveryConventionTest.cs b/test/EntityFramework.Core.Tests/Metadata/ModelConventions/RelationshipDiscoveryConventionTest.cs index 3e87d865595..4f4c157d13d 100644 --- a/test/EntityFramework.Core.Tests/Metadata/ModelConventions/RelationshipDiscoveryConventionTest.cs +++ b/test/EntityFramework.Core.Tests/Metadata/ModelConventions/RelationshipDiscoveryConventionTest.cs @@ -52,7 +52,7 @@ public void One_to_one_bidirectional_is_discovered() Assert.Same(entityBuilder, new RelationshipDiscoveryConvention().Apply(entityBuilder)); VerifyRelationship(entityBuilder.Metadata.GetNavigations().Single(), OneToOneDependent.NavigationProperty.Name, unique: true); - Assert.Equal(2, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -67,7 +67,7 @@ public void One_to_many_unidirectional_is_upgraded_to_one_to_one_bidirectional() Assert.Same(dependentEntityBuilder, new RelationshipDiscoveryConvention().Apply(dependentEntityBuilder)); VerifyRelationship(dependentEntityBuilder.Metadata.GetNavigations().Single(), OneToOnePrincipal.NavigationProperty.Name, unique: true); - Assert.Equal(2, principalEntityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, principalEntityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -85,7 +85,7 @@ public void Two_one_to_many_unidirectional_are_upgraded_to_one_to_one_bidirectio Assert.Same(dependentEntityBuilder, new RelationshipDiscoveryConvention().Apply(dependentEntityBuilder)); VerifyRelationship(dependentEntityBuilder.Metadata.GetNavigations().Single(), OneToOnePrincipal.NavigationProperty.Name, unique: true); - Assert.Equal(2, principalEntityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, principalEntityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -100,7 +100,7 @@ public void One_to_many_unidirectional_is_not_upgraded_to_one_to_one_bidirection Assert.Same(dependentEntityBuilder, new RelationshipDiscoveryConvention().Apply(dependentEntityBuilder)); VerifyRelationship(principalEntityBuilder.Metadata.GetNavigations().Single(), null, unique: false, singleRelationship: false); VerifyRelationship(dependentEntityBuilder.Metadata.GetNavigations().Single(), null, unique: false, singleRelationship: false); - Assert.Equal(2, principalEntityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, principalEntityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -111,7 +111,7 @@ public void One_to_many_unidirectional_is_discovered() Assert.Same(entityBuilder, new RelationshipDiscoveryConvention().Apply(entityBuilder)); VerifyRelationship(entityBuilder.Metadata.GetNavigations().Single(), null, unique: false); - Assert.Equal(2, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -125,7 +125,7 @@ public void One_to_many_unidirectional_is_upgraded_to_one_to_many_bidirectional( Assert.Same(dependentEntityBuilder, new RelationshipDiscoveryConvention().Apply(dependentEntityBuilder)); VerifyRelationship(dependentEntityBuilder.Metadata.GetNavigations().Single(), OneToManyPrincipal.NavigationProperty.Name, unique: false); - Assert.Equal(2, principalEntityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, principalEntityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -140,7 +140,7 @@ public void One_to_many_unidirectional_is_not_upgraded_to_one_to_many_bidirectio VerifyRelationship(principalEntityBuilder.Metadata.GetNavigations().Single(), null, unique: false, singleRelationship: false); VerifyRelationship(dependentEntityBuilder.Metadata.GetNavigations().Single(), null, unique: false, singleRelationship: false); - Assert.Equal(2, principalEntityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, principalEntityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -151,7 +151,7 @@ public void One_to_many_bidirectional_is_discovered() Assert.Same(entityBuilder, new RelationshipDiscoveryConvention().Apply(entityBuilder)); VerifyRelationship(entityBuilder.Metadata.GetNavigations().Single(), OneToManyPrincipal.NavigationProperty.Name, unique: false); - Assert.Equal(2, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -162,7 +162,7 @@ public void Many_to_one_unidirectional_is_discovered() Assert.Same(entityBuilder, new RelationshipDiscoveryConvention().Apply(entityBuilder)); VerifyRelationship(entityBuilder.Metadata.GetNavigations().Single(), null, unique: false); - Assert.Equal(2, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -176,7 +176,7 @@ public void Many_to_one_unidirectional_is_upgraded_to_many_to_one_bidirectional( Assert.Same(principalEntityBuilder, new RelationshipDiscoveryConvention().Apply(principalEntityBuilder)); VerifyRelationship(principalEntityBuilder.Metadata.GetNavigations().Single(), OneToManyDependent.NavigationProperty.Name, unique: false); - Assert.Equal(2, principalEntityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, principalEntityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -191,7 +191,7 @@ public void Many_to_one_unidirectional_is_not_upgraded_to_many_to_one_bidirectio VerifyRelationship(principalEntityBuilder.Metadata.GetNavigations().Single(), null, unique: false, singleRelationship: false); VerifyRelationship(dependentEntityBuilder.Metadata.GetNavigations().Single(), null, unique: false, singleRelationship: false); - Assert.Equal(2, principalEntityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, principalEntityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -202,7 +202,7 @@ public void Many_to_one_bidirectional_is_discovered() Assert.Same(entityBuilder, new RelationshipDiscoveryConvention().Apply(entityBuilder)); VerifyRelationship(entityBuilder.Metadata.GetNavigations().Single(), OneToManyDependent.NavigationProperty.Name, unique: false); - Assert.Equal(2, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -215,7 +215,7 @@ public void Many_to_many_bidirectional_is_not_discovered() Assert.Empty(entityBuilder.Metadata.GetForeignKeys()); Assert.Empty(entityBuilder.Metadata.GetNavigations()); - Assert.Equal(1, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(1, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -227,7 +227,7 @@ public void Ambiguous_navigations_are_not_discovered() Assert.Empty(entityBuilder.Metadata.GetForeignKeys()); Assert.Empty(entityBuilder.Metadata.GetNavigations()); - Assert.Equal(2, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -243,7 +243,7 @@ public void Existing_relationship_is_removed_if_ambiguous() Assert.Empty(entityBuilderFirst.Metadata.GetForeignKeys()); Assert.Empty(entityBuilderFirst.Metadata.GetNavigations()); Assert.Empty(entityBuilderSecond.Metadata.GetNavigations()); - Assert.Equal(2, entityBuilderFirst.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, entityBuilderFirst.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -258,7 +258,7 @@ public void Existing_relationship_removes_ambiguity_if_higher_source() VerifyRelationship(entityBuilderFirst.Metadata.FindNavigation(MultipleNavigationsFirst.CollectionNavigationProperty.Name), null, unique: false, singleRelationship: false); VerifyRelationship(entityBuilderFirst.Metadata.FindNavigation(MultipleNavigationsFirst.NonCollectionNavigationProperty.Name), nameof(MultipleNavigationsSecond.MultipleNavigationsFirst), unique: true, singleRelationship: false); - Assert.Equal(2, entityBuilderFirst.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, entityBuilderFirst.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -273,7 +273,7 @@ public void Navigations_are_not_discovered_if_ambiguous_inverse() Assert.Empty(entityBuilderFirst.Metadata.GetForeignKeys()); Assert.Empty(entityBuilderFirst.Metadata.GetNavigations()); Assert.Empty(entityBuilderSecond.Metadata.GetNavigations()); - Assert.Equal(2, entityBuilderFirst.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, entityBuilderFirst.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -289,7 +289,7 @@ public void Existing_relationship_is_removed_if_ambiguous_inverse() Assert.Empty(entityBuilderFirst.Metadata.GetForeignKeys()); Assert.Empty(entityBuilderFirst.Metadata.GetNavigations()); Assert.Empty(entityBuilderSecond.Metadata.GetNavigations()); - Assert.Equal(2, entityBuilderFirst.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, entityBuilderFirst.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -304,7 +304,7 @@ public void Existing_relationship_removes_ambiguity_in_inverse_if_higher_source( VerifyRelationship(entityBuilderFirst.Metadata.FindNavigation(MultipleNavigationsFirst.CollectionNavigationProperty.Name), null, unique: false, singleRelationship: false); VerifyRelationship(entityBuilderFirst.Metadata.FindNavigation(MultipleNavigationsFirst.NonCollectionNavigationProperty.Name), nameof(MultipleNavigationsSecond.MultipleNavigationsFirst), unique: true, singleRelationship: false); - Assert.Equal(2, entityBuilderFirst.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, entityBuilderFirst.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -358,7 +358,7 @@ public void Navigations_to_base_and_derived_are_discovered() Assert.Empty(baseFk.FindNavigationsTo(entityBuilder.Metadata)); Assert.Empty(derivedFk.FindNavigationsTo(entityBuilder.Metadata)); Assert.Equal(2, entityBuilder.Metadata.GetNavigations().Count()); - Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -381,7 +381,7 @@ public void Navigations_to_base_and_derived_are_discovered_if_inverse_from_base( Assert.Equal(nameof(Base.BaseNavigation), baseFk.FindNavigationsTo(entityBuilder.Metadata).Single().Name); Assert.Empty(derivedFk.FindNavigationsTo(entityBuilder.Metadata)); Assert.Equal(2, entityBuilder.Metadata.GetNavigations().Count()); - Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -404,7 +404,7 @@ public void Navigations_to_derived_and_base_are_discovered_if_inverse_from_base( Assert.Equal(nameof(Base.BaseNavigation), baseFk.FindNavigationsTo(entityBuilder.Metadata).Single().Name); Assert.Empty(derivedFk.FindNavigationsTo(entityBuilder.Metadata)); Assert.Equal(2, entityBuilder.Metadata.GetNavigations().Count()); - Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -427,7 +427,7 @@ public void Navigations_to_base_and_derived_are_discovered_if_inverse_from_deriv Assert.Empty(baseFk.FindNavigationsTo(entityBuilder.Metadata)); Assert.Equal(nameof(DerivedOne.DerivedNavigation), derivedFk.FindNavigationsTo(entityBuilder.Metadata).Single().Name); Assert.Equal(2, entityBuilder.Metadata.GetNavigations().Count()); - Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -450,7 +450,7 @@ public void Navigation_pairs_to_base_and_derived_are_discovered() Assert.Equal(nameof(Base.BaseNavigation), baseFk.FindNavigationsTo(entityBuilder.Metadata).Single().Name); Assert.Equal(nameof(DerivedOne.DerivedNavigation), derivedFk.FindNavigationsTo(entityBuilder.Metadata).Single().Name); Assert.Equal(3, entityBuilder.Metadata.GetNavigations().Count()); - Assert.Equal(4, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(4, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -466,7 +466,7 @@ public void Navigation_to_base_is_discovered() VerifyRelationship(entityBuilder.Metadata.FindNavigation(nameof(NavigationsToBaseAndDerived.Base)), expectedInverseName: nameof(Base.BaseNavigation), unique: true); - Assert.Equal(2, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -488,7 +488,7 @@ public void Existing_navigation_to_derived_is_promoted() VerifyRelationship(entityBuilder.Metadata.FindNavigation(nameof(NavigationsToBaseAndDerived.Base)), expectedInverseName: nameof(Base.BaseNavigation), unique: true); Assert.Empty(derivedBuilder.Metadata.GetDeclaredNavigations()); - Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -510,7 +510,7 @@ public void Existing_navigation_from_derived_is_promoted() VerifyRelationship(baseBuilder.Metadata.FindNavigation(nameof(Base.BaseNavigation)), expectedInverseName: nameof(NavigationsToBaseAndDerived.Base), unique: true); Assert.Empty(derivedBuilder.Metadata.GetDeclaredNavigations()); - Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -530,7 +530,7 @@ public void Navigation_from_derived_is_not_discovered_if_ambiguous() Assert.Empty(entityBuilder.Metadata.GetForeignKeys()); Assert.Empty(derivedBuilder.Metadata.GetNavigations()); Assert.Empty(derivedBuilder.Metadata.GetForeignKeys()); - Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -550,7 +550,7 @@ public void Existing_relationship_to_base_removes_ambiguity() VerifyRelationship(baseBuilder.Metadata.GetNavigations().Single(), expectedInverseName: null, unique: false, singleRelationship: false); VerifyRelationship(entityBuilder.Metadata.GetNavigations().Single(), nameof(DerivedOne.DerivedNavigation), unique: true, singleRelationship: false); - Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -570,7 +570,7 @@ public void Navigation_to_derived_is_not_discovered_if_inverse_ambiguous() Assert.Empty(entityBuilder.Metadata.GetForeignKeys()); Assert.Empty(derivedBuilder.Metadata.GetNavigations()); Assert.Empty(derivedBuilder.Metadata.GetForeignKeys()); - Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -590,7 +590,7 @@ public void Existing_relationship_to_base_removes_ambiguity_in_derived_inverse() VerifyRelationship(baseBuilder.Metadata.GetNavigations().Single(), expectedInverseName: null, unique: false, singleRelationship: false); VerifyRelationship(entityBuilder.Metadata.GetNavigations().Single(), nameof(DerivedOne.DerivedNavigation), unique: true, singleRelationship: false); - Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -611,7 +611,7 @@ public void Navigation_to_derived_is_discovered() .Single(n => n.Name == nameof(NavigationsToBaseAndDerived.DerivedOne)).ForeignKey; Assert.Equal(nameof(DerivedOne.DerivedNavigation), derivedFk.FindNavigationsTo(entityBuilder.Metadata).Single().Name); Assert.Equal(1, entityBuilder.Metadata.GetNavigations().Count()); - Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -632,7 +632,7 @@ public void Navigation_to_derived_is_discovered_if_inverse_inherited() .Single(n => n.Name == nameof(NavigationsToBaseAndDerived.DerivedOne)).ForeignKey; Assert.Equal(nameof(Base.BaseNavigation), derivedFk.FindNavigationsTo(entityBuilder.Metadata).Single().Name); Assert.Equal(1, entityBuilder.Metadata.GetNavigations().Count()); - Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(3, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -650,7 +650,7 @@ public void Navigation_to_base_is_not_discovered_if_base_ignored() Assert.Empty(entityBuilder.Metadata.GetForeignKeys()); Assert.Empty(entityBuilder.Metadata.GetNavigations()); - Assert.Equal(2, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] @@ -668,7 +668,7 @@ public void Navigation_to_derived_is_discovered_if_base_ignored() var derivedFk = entityBuilder.Metadata.FindNavigation(nameof(NavigationsToBaseAndDerived.DerivedOne)).ForeignKey; Assert.Equal(nameof(DerivedOne.BaseNavigation), derivedFk.FindNavigationsTo(entityBuilder.Metadata).Single().Name); Assert.Equal(1, entityBuilder.Metadata.GetNavigations().Count()); - Assert.Equal(2, entityBuilder.Metadata.Model.GetEntityTypes().Count); + Assert.Equal(2, entityBuilder.Metadata.Model.GetEntityTypes().Count()); } [Fact] diff --git a/test/EntityFramework.Core.Tests/ModelBuilderTest/NonRelationshipTestBase.cs b/test/EntityFramework.Core.Tests/ModelBuilderTest/NonRelationshipTestBase.cs index c90cd49043b..b6c92e44d06 100644 --- a/test/EntityFramework.Core.Tests/ModelBuilderTest/NonRelationshipTestBase.cs +++ b/test/EntityFramework.Core.Tests/ModelBuilderTest/NonRelationshipTestBase.cs @@ -360,7 +360,7 @@ public virtual void Ignoring_a_navigation_property_removes_discovered_entity_typ modelBuilder.Validate(); - Assert.Equal(1, model.GetEntityTypes().Count); + Assert.Equal(1, model.GetEntityTypes().Count()); } [Fact] @@ -377,9 +377,9 @@ public virtual void Ignoring_a_navigation_property_removes_discovered_relationsh modelBuilder.Validate(); - Assert.Equal(0, model.GetEntityTypes()[0].GetForeignKeys().Count()); - Assert.Equal(0, model.GetEntityTypes()[1].GetForeignKeys().Count()); - Assert.Equal(2, model.GetEntityTypes().Count); + Assert.Equal(0, model.GetEntityTypes().First().GetForeignKeys().Count()); + Assert.Equal(0, model.GetEntityTypes().Last().GetForeignKeys().Count()); + Assert.Equal(2, model.GetEntityTypes().Count()); } [Fact]