/// <summary>
        ///     Initializes a new instance of the <see cref="InternalNestedPropertyEntry" /> class.
        /// </summary>
        /// <param name="parentPropertyEntry"> The parent property entry. </param>
        /// <param name="propertyMetadata"> The property metadata. </param>
        public InternalNestedPropertyEntry(
            InternalPropertyEntry parentPropertyEntry, PropertyEntryMetadata propertyMetadata)
            : base(parentPropertyEntry.InternalEntityEntry, propertyMetadata)
        {
            Contract.Requires(parentPropertyEntry != null);

            _parentPropertyEntry = parentPropertyEntry;
        }
        /// <summary>
        ///     Initializes a new instance of the <see cref="InternalNestedPropertyEntry" /> class.
        /// </summary>
        /// <param name="parentPropertyEntry"> The parent property entry. </param>
        /// <param name="propertyMetadata"> The property metadata. </param>
        public InternalNestedPropertyEntry(
            InternalPropertyEntry parentPropertyEntry, PropertyEntryMetadata propertyMetadata)
            : base(parentPropertyEntry.InternalEntityEntry, propertyMetadata)
        {
            DebugCheck.NotNull(parentPropertyEntry);

            _parentPropertyEntry = parentPropertyEntry;
        }
        // <summary>
        // Creates a new <see cref="InternalMemberEntry" /> the runtime type of which will be
        // determined by the metadata.
        // </summary>
        // <param name="internalEntityEntry"> The entity entry to which the member belongs. </param>
        // <param name="parentPropertyEntry"> The parent property entry which will always be null for navigation entries. </param>
        // <returns> The new entry. </returns>
        public override InternalMemberEntry CreateMemberEntry(
            InternalEntityEntry internalEntityEntry, InternalPropertyEntry parentPropertyEntry)
        {
            Debug.Assert(parentPropertyEntry == null, "Navigation entries cannot be nested; parentPropertyEntry must be null.");

            return _isCollection
                       ? (InternalMemberEntry)new InternalCollectionEntry(internalEntityEntry, this)
                       : new InternalReferenceEntry(internalEntityEntry, this);
        }
        /// <summary>
        ///     Validates type properties. Any validation errors will be added to <paramref name = "validationErrors" />
        ///     collection.
        /// </summary>
        /// <param name = "entityValidationContext">
        ///     Validation context. Must not be null.
        /// </param>
        /// <param name = "validationErrors">
        ///     Collection of validation errors. Any validation errors will be added to it.
        /// </param>
        /// <param name = "parentProperty">The entry for the complex property. Null if validating an entity.</param>
        /// <remarks>
        ///     Note that <paramref name = "validationErrors" /> will be modified by this method. Errors should be only added,
        ///     never removed or changed. Taking a collection as a modifiable parameter saves a couple of memory allocations
        ///     and a merge of validation error lists per entity.
        /// </remarks>
        protected override void ValidateProperties(
            EntityValidationContext entityValidationContext, InternalPropertyEntry parentProperty,
            List<DbValidationError> validationErrors)
        {
            var entityEntry = entityValidationContext.InternalEntity;

            foreach (var validator in PropertyValidators)
            {
                validationErrors.AddRange(
                    validator.Validate(entityValidationContext, entityEntry.Member(validator.PropertyName)));
            }
        }
        /// <summary>
        ///     Validates type properties. Any validation errors will be added to <paramref name = "validationErrors" />
        ///     collection.
        /// </summary>
        /// <param name = "entityValidationContext">
        ///     Validation context. Must not be null.
        /// </param>
        /// <param name = "validationErrors">
        ///     Collection of validation errors. Any validation errors will be added to it.
        /// </param>
        /// <param name = "parentProperty">The entry for the complex property. Null if validating an entity.</param>
        /// <remarks>
        ///     Note that <paramref name = "validationErrors" /> will be modified by this method. Errors should be only added,
        ///     never removed or changed. Taking a collection as a modifiable parameter saves a couple of memory allocations
        ///     and a merge of validation error lists per entity.
        /// </remarks>
        protected override void ValidateProperties(
            EntityValidationContext entityValidationContext, InternalPropertyEntry parentProperty,
            List<DbValidationError> validationErrors)
        {
            Contract.Assert(parentProperty.EntryMetadata.IsComplex, "A complex type expected.");
            Contract.Assert(parentProperty.CurrentValue != null);

            foreach (var validator in PropertyValidators)
            {
                var complexProperty = parentProperty.Property(validator.PropertyName);
                validationErrors.AddRange(validator.Validate(entityValidationContext, complexProperty));
            }
        }
        /// <summary>
        ///     Validates an instance.
        /// </summary>
        /// <param name = "entityValidationContext">Entity validation context. Must not be null.</param>
        /// <param name = "property">The entry for the complex property. Null if validating an entity.</param>
        /// <returns><see cref = "DbEntityValidationResult" /> instance. Never null.</returns>
        /// <remarks>
        ///     Protected so it doesn't appear on EntityValidator.
        /// </remarks>
        protected IEnumerable<DbValidationError> Validate(
            EntityValidationContext entityValidationContext, InternalPropertyEntry property)
        {
            var validationErrors = new List<DbValidationError>();

            ValidateProperties(entityValidationContext, property, validationErrors);

            // only run type level validation if all properties were validated successfully
            if (!validationErrors.Any())
            {
                foreach (var typeLevelValidator in _typeLevelValidators)
                {
                    validationErrors.AddRange(typeLevelValidator.Validate(entityValidationContext, property));
                }
            }

            return validationErrors;
        }
 /// <summary>
 ///     Validates type properties. Any validation errors will be added to <paramref name = "validationErrors" />
 ///     collection.
 /// </summary>
 /// <param name = "entityValidationContext">
 ///     Validation context. Must not be null.
 /// </param>
 /// <param name = "validationErrors">
 ///     Collection of validation errors. Any validation errors will be added to it.
 /// </param>
 /// <param name = "parentProperty">The entry for the complex property. Null if validating an entity.</param>
 /// <remarks>
 ///     Note that <paramref name = "validationErrors" /> will be modified by this method. Errors should be only added,
 ///     never removed or changed. Taking a collection as a modifiable parameter saves a couple of memory allocations
 ///     and a merge of validation error lists per entity.
 /// </remarks>
 protected abstract void ValidateProperties(
     EntityValidationContext entityValidationContext, InternalPropertyEntry parentProperty,
     List<DbValidationError> validationErrors);
 protected override void ValidateProperties(
     EntityValidationContext entityValidationContext, InternalPropertyEntry parentProperty,
     List<DbValidationError> validationErrors)
 {
     //Contract.Requires(entityValidationContext != null);
     //Contract.Requires(validationErrors != null);
 }
 /// <summary>
 ///     Creates a new <see cref = "InternalMemberEntry" /> the runtime type of which will be
 ///     determined by the metadata.
 /// </summary>
 /// <param name = "internalEntityEntry">The entity entry to which the member belongs.</param>
 /// <param name = "parentPropertyEntry">The parent property entry if the new entry is nested, otherwise null.</param>
 /// <returns>The new entry.</returns>
 public override InternalMemberEntry CreateMemberEntry(
     InternalEntityEntry internalEntityEntry, InternalPropertyEntry parentPropertyEntry)
 {
     return parentPropertyEntry == null
                ? (InternalMemberEntry)new InternalEntityPropertyEntry(internalEntityEntry, this)
                : new InternalNestedPropertyEntry(parentPropertyEntry, this);
 }
        /// <summary>
        ///     Gets an internal object representing a scalar or complex property.
        ///     The property may be a nested property on the given <see cref = "InternalPropertyEntry" />.
        /// </summary>
        /// <param name = "parentProperty">The parent property entry, or null if this is a property directly on the entity.</param>
        /// <param name = "propertyName">Name of the property.</param>
        /// <param name = "properties">The property split out into its parts.</param>
        /// <param name = "requestedType">The type of object requested, which may be null or 'object' if any type can be accepted.</param>
        /// <param name = "requireComplex">if set to <c>true</c> then the found property must be a complex property.</param>
        /// <returns>The entry.</returns>
        private InternalPropertyEntry Property(
            InternalPropertyEntry parentProperty, string propertyName, IList<string> properties, Type requestedType,
            bool requireComplex)
        {
            var isDotted = properties.Count > 1;
            var currentRequestedType = isDotted ? typeof(object) : requestedType;
            var declaringType = parentProperty != null ? parentProperty.EntryMetadata.ElementType : EntityType;

            var propertyMetadata = ValidateAndGetPropertyMetadata(properties[0], declaringType, currentRequestedType);

            if (propertyMetadata == null
                || ((isDotted || requireComplex) && !propertyMetadata.IsComplex))
            {
                if (isDotted)
                {
                    throw Error.DbEntityEntry_DottedPartNotComplex(properties[0], propertyName, declaringType.Name);
                }
                throw requireComplex
                          ? Error.DbEntityEntry_NotAComplexProperty(properties[0], declaringType.Name)
                          : Error.DbEntityEntry_NotAScalarProperty(properties[0], declaringType.Name);
            }

            var internalPropertyEntry = (InternalPropertyEntry)propertyMetadata.CreateMemberEntry(this, parentProperty);
            return isDotted
                       ? Property(
                           internalPropertyEntry, propertyName, properties.Skip(1).ToList(), requestedType,
                           requireComplex)
                       : internalPropertyEntry;
        }
 /// <summary>
 ///     Gets an internal object representing a scalar or complex property.
 ///     The property may be a nested property on the given <see cref = "InternalPropertyEntry" />.
 /// </summary>
 /// <param name = "parentProperty">The parent property entry, or null if this is a property directly on the entity.</param>
 /// <param name = "propertyName">Name of the property.</param>
 /// <param name = "requestedType">The type of object requested, which may be null or 'object' if any type can be accepted.</param>
 /// <param name = "requireComplex">if set to <c>true</c> then the found property must be a complex property.</param>
 /// <returns>The entry.</returns>
 public InternalPropertyEntry Property(
     InternalPropertyEntry parentProperty, string propertyName, Type requestedType, bool requireComplex)
 {
     return Property(parentProperty, propertyName, SplitName(propertyName), requestedType, requireComplex);
 }
 /// <summary>
 ///     Validates an instance.
 /// </summary>
 /// <param name = "entityValidationContext">Entity validation context. Must not be null.</param>
 /// <param name = "property">The entry for the complex property. Null if validating an entity.</param>
 /// <returns><see cref = "DbEntityValidationResult" /> instance. Never null.</returns>
 public new IEnumerable<DbValidationError> Validate(
     EntityValidationContext entityValidationContext, InternalPropertyEntry property)
 {
     return base.Validate(entityValidationContext, property);
 }
 /// <summary>
 ///     Creates a new <see cref = "InternalMemberEntry" /> the runtime type of which will be
 ///     determined by the metadata.
 /// </summary>
 /// <param name = "internalEntityEntry">The entity entry to which the member belongs.</param>
 /// <param name = "parentPropertyEntry">The parent property entry if the new entry is nested, otherwise null.</param>
 /// <returns>The new entry.</returns>
 public abstract InternalMemberEntry CreateMemberEntry(
     InternalEntityEntry internalEntityEntry, InternalPropertyEntry parentPropertyEntry);