private NavigationPropertyConfiguration AddNavigationProperty(PropertyInfo navigationProperty, EdmMultiplicity multiplicity, bool containsTarget)
        {
            if (navigationProperty == null)
            {
                throw new ArgumentNullException(nameof(navigationProperty));
            }

            if (!TypeHelper.GetReflectedType(navigationProperty).IsAssignableFrom(ClrType))
            {
                throw Error.Argument("navigationProperty", SRResources.PropertyDoesNotBelongToType, navigationProperty.Name, ClrType.FullName);
            }

            ValidatePropertyNotAlreadyDefinedInBaseTypes(navigationProperty);
            ValidatePropertyNotAlreadyDefinedInDerivedTypes(navigationProperty);

            PropertyConfiguration           propertyConfig;
            NavigationPropertyConfiguration navigationPropertyConfig;

            if (ExplicitProperties.ContainsKey(navigationProperty))
            {
                propertyConfig = ExplicitProperties[navigationProperty];
                if (propertyConfig.Kind != PropertyKind.Navigation)
                {
                    throw Error.Argument("navigationProperty", SRResources.MustBeNavigationProperty, navigationProperty.Name, ClrType.FullName);
                }

                navigationPropertyConfig = propertyConfig as NavigationPropertyConfiguration;
                if (navigationPropertyConfig.Multiplicity != multiplicity)
                {
                    throw Error.Argument("navigationProperty", SRResources.MustHaveMatchingMultiplicity, navigationProperty.Name, multiplicity);
                }
            }
            else
            {
                navigationPropertyConfig = new NavigationPropertyConfiguration(
                    navigationProperty,
                    multiplicity,
                    this);
                if (containsTarget)
                {
                    navigationPropertyConfig = navigationPropertyConfig.Contained();
                }

                ExplicitProperties[navigationProperty] = navigationPropertyConfig;
                // make sure the related type is configured
                ModelBuilder.AddEntityType(navigationPropertyConfig.RelatedClrType);
            }
            return(navigationPropertyConfig);
        }
        private void VerifyBindingPath(NavigationPropertyConfiguration navigationConfiguration, IList <MemberInfo> bindingPath)
        {
            Contract.Assert(navigationConfiguration != null);
            Contract.Assert(bindingPath != null);

            PropertyInfo navigation = bindingPath.Last() as PropertyInfo;

            if (navigation == null || navigation != navigationConfiguration.PropertyInfo)
            {
                throw Error.Argument("navigationConfiguration", SRResources.NavigationPropertyBindingPathIsNotValid,
                                     bindingPath.ConvertBindingPath(), navigationConfiguration.Name);
            }

            bindingPath.Aggregate(EntityType.ClrType, VerifyBindingSegment);
        }
        /// <summary>
        /// Removes the binding for the given navigation property and the given binding path.
        /// </summary>
        /// <param name="navigationConfiguration">The navigation property.</param>
        /// <param name="bindingPath">The binding path.</param>
        public virtual void RemoveBinding(NavigationPropertyConfiguration navigationConfiguration, string bindingPath)
        {
            if (navigationConfiguration == null)
            {
                throw Error.ArgumentNull("navigationConfiguration");
            }

            Dictionary <string, NavigationPropertyBindingConfiguration> navigationPropertyBindingMap;

            if (_navigationPropertyBindings.TryGetValue(navigationConfiguration, out navigationPropertyBindingMap))
            {
                navigationPropertyBindingMap.Remove(bindingPath);

                if (!navigationPropertyBindingMap.Any())
                {
                    _navigationPropertyBindings.Remove(navigationConfiguration);
                }
            }
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="NavigationPropertyBindingConfiguration"/> class.
        /// </summary>
        /// <param name="navigationProperty">The navigation property for the binding.</param>
        /// <param name="navigationSource">The target navigation source of the binding.</param>
        /// <param name="path">The path of current binding.</param>
        public NavigationPropertyBindingConfiguration(NavigationPropertyConfiguration navigationProperty,
                                                      NavigationSourceConfiguration navigationSource, IList <MemberInfo> path)
        {
            if (navigationProperty == null)
            {
                throw Error.ArgumentNull("navigationProperty");
            }

            if (navigationSource == null)
            {
                throw Error.ArgumentNull("navigationSource");
            }

            if (path == null)
            {
                throw Error.ArgumentNull("path");
            }

            NavigationProperty     = navigationProperty;
            TargetNavigationSource = navigationSource;
            Path = path;
        }
Exemple #5
0
        public NavigationPropertyBindingConfiguration HasOptionalBinding <TTargetType, TDerivedType>(
            Expression <Func <TDerivedType, TTargetType> > navigationExpression,
            string targetEntitySet)
            where TTargetType : class
            where TDerivedType : class, TStructuralType
        {
            if (navigationExpression == null)
            {
                throw Error.ArgumentNull("navigationExpression");
            }

            if (String.IsNullOrEmpty(targetEntitySet))
            {
                throw Error.ArgumentNullOrEmpty("targetEntitySet");
            }

            StructuralTypeConfiguration <TDerivedType> derivedConfiguration;

            if (this._structuralType.Configuration.Kind == EdmTypeKind.Entity)
            {
                derivedConfiguration = _modelBuilder.EntityType <TDerivedType>().DerivesFrom <TStructuralType>();
            }
            else
            {
                derivedConfiguration = _modelBuilder.ComplexType <TDerivedType>().DerivesFrom <TStructuralType>();
            }

            NavigationPropertyConfiguration navigation = derivedConfiguration.HasOptional(navigationExpression);

            IList <MemberInfo> bindingPath = new List <MemberInfo>(_bindingPath);

            bindingPath.Add(TypeHelper.AsMemberInfo(typeof(TDerivedType)));
            bindingPath.Add(navigation.PropertyInfo);

            NavigationSourceConfiguration entitySet = _modelBuilder.EntitySet <TTargetType>(targetEntitySet).Configuration;

            return(this._navigationSource.AddBinding(navigation, entitySet, bindingPath));
        }
        /// <summary>
        /// Binds the given navigation property to the target navigation source.
        /// </summary>
        /// <param name="navigationConfiguration">The navigation property.</param>
        /// <param name="targetNavigationSource">The target navigation source.</param>
        /// <returns>The <see cref="NavigationPropertyBindingConfiguration"/> so that it can be further configured.</returns>
        public virtual NavigationPropertyBindingConfiguration AddBinding(NavigationPropertyConfiguration navigationConfiguration,
                                                                         NavigationSourceConfiguration targetNavigationSource)
        {
            if (navigationConfiguration == null)
            {
                throw Error.ArgumentNull("navigationConfiguration");
            }

            if (targetNavigationSource == null)
            {
                throw Error.ArgumentNull("targetNavigationSource");
            }

            IList <MemberInfo> bindingPath = new List <MemberInfo> {
                navigationConfiguration.PropertyInfo
            };

            if (navigationConfiguration.DeclaringType != EntityType)
            {
                bindingPath.Insert(0, TypeHelper.AsMemberInfo(navigationConfiguration.DeclaringType.ClrType));
            }

            return(AddBinding(navigationConfiguration, targetNavigationSource, bindingPath));
        }
 /// <summary>
 /// Finds the <see cref="NavigationPropertyBindingConfiguration"/> for the given navigation property.
 /// </summary>
 /// <param name="navigationConfiguration">The navigation property.</param>
 /// <param name="bindingPath">The navigation binding path.</param>
 /// <returns>The binding if found.</returns>
 public NavigationPropertyBindingConfiguration FindBinding(NavigationPropertyConfiguration navigationConfiguration,
                                                           IList <MemberInfo> bindingPath)
 {
     return(_configuration.FindBinding(navigationConfiguration, bindingPath));
 }
 /// <summary>
 /// Finds the bindings <see cref="NavigationPropertyBindingConfiguration"/> for the given navigation property
 /// </summary>
 /// <param name="navigationConfiguration">The navigation property.</param>
 /// <returns>The bindings if found</returns>
 public IEnumerable <NavigationPropertyBindingConfiguration> FindBinding(NavigationPropertyConfiguration navigationConfiguration)
 {
     return(_configuration.FindBinding(navigationConfiguration));
 }
        /// <summary>
        /// Finds the binding for the given navigation property and tries to create it if it does not exist.
        /// </summary>
        /// <param name="navigationConfiguration">The navigation property.</param>
        /// <param name="bindingPath">The binding path.</param>
        /// <returns>The <see cref="NavigationPropertyBindingConfiguration"/> so that it can be further configured.</returns>
        public virtual NavigationPropertyBindingConfiguration FindBinding(NavigationPropertyConfiguration navigationConfiguration,
                                                                          IList <MemberInfo> bindingPath)
        {
            if (navigationConfiguration == null)
            {
                throw Error.ArgumentNull("navigationConfiguration");
            }

            if (bindingPath == null)
            {
                throw Error.ArgumentNullOrEmpty("bindingPath");
            }

            string path = bindingPath.ConvertBindingPath();

            Dictionary <string, NavigationPropertyBindingConfiguration> navigationPropertyBindings;

            if (_navigationPropertyBindings.TryGetValue(navigationConfiguration, out navigationPropertyBindings))
            {
                NavigationPropertyBindingConfiguration bindingConfiguration;
                if (navigationPropertyBindings.TryGetValue(path, out bindingConfiguration))
                {
                    return(bindingConfiguration);
                }
            }

            if (_modelBuilder.BindingOptions == NavigationPropertyBindingOption.None)
            {
                return(null);
            }

            bool hasSingletonAttribute = navigationConfiguration.PropertyInfo.GetCustomAttributes <SingletonAttribute>().Any();
            Type entityType            = navigationConfiguration.RelatedClrType;

            NavigationSourceConfiguration[] matchedNavigationSources;
            if (hasSingletonAttribute)
            {
                matchedNavigationSources = _modelBuilder.Singletons.Where(es => es.EntityType.ClrType == entityType).ToArray();
            }
            else
            {
                matchedNavigationSources = _modelBuilder.EntitySets.Where(es => es.EntityType.ClrType == entityType).ToArray();
            }

            if (matchedNavigationSources.Length >= 1)
            {
                if (matchedNavigationSources.Length == 1 ||
                    _modelBuilder.BindingOptions == NavigationPropertyBindingOption.Auto)
                {
                    return(AddBinding(navigationConfiguration, matchedNavigationSources[0], bindingPath));
                }

                throw Error.NotSupported(
                          SRResources.CannotAutoCreateMultipleCandidates,
                          path,
                          navigationConfiguration.DeclaringType.FullName,
                          Name,
                          String.Join(", ", matchedNavigationSources.Select(s => s.Name)));
            }

            return(null);
        }
        /// <summary>
        /// Finds the bindings <see cref="NavigationPropertyBindingConfiguration"/> for the given navigation property.
        /// </summary>
        /// <param name="navigationConfiguration">The navigation property.</param>
        /// <returns>The list of <see cref="NavigationPropertyBindingConfiguration"/> so that it can be further configured.</returns>
        public virtual IEnumerable <NavigationPropertyBindingConfiguration> FindBinding(NavigationPropertyConfiguration navigationConfiguration)
        {
            if (navigationConfiguration == null)
            {
                throw Error.ArgumentNull("navigationConfiguration");
            }

            Dictionary <string, NavigationPropertyBindingConfiguration> navigationPropertyBindings;

            if (_navigationPropertyBindings.TryGetValue(navigationConfiguration, out navigationPropertyBindings))
            {
                return(navigationPropertyBindings.Values);
            }

            return(null);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="NavigationPropertyBindingConfiguration"/> class.
 /// </summary>
 /// <param name="navigationProperty">The navigation property for the binding.</param>
 /// <param name="navigationSource">The target navigation source of the binding.</param>
 public NavigationPropertyBindingConfiguration(NavigationPropertyConfiguration navigationProperty,
                                               NavigationSourceConfiguration navigationSource)
     : this(navigationProperty, navigationSource, new MemberInfo[] { navigationProperty?.PropertyInfo })
 {
 }