Esempio n. 1
0
        /// <summary>
        /// Generates code (AST) for single association in both directions using properties and/or extension methods.
        /// </summary>
        /// <param name="association">Association model.</param>
        /// <param name="extensionAssociations">Association extensions region provider.</param>
        /// <param name="entityAssociations">Assocation property groups for each entity.</param>
        /// <param name="extensionEntityAssociations">Association methods groupsfor each entity.</param>
        private void BuildAssociation(
            AssociationModel association,
            Func <RegionGroup> extensionAssociations,
            Dictionary <EntityModel, PropertyGroup> entityAssociations,
            Dictionary <EntityModel, MethodGroup> extensionEntityAssociations)
        {
            // get source and target entities for association
            // source is foreign key source table
            // target is foreign key target table
            if (!_entityBuilders.TryGetValue(association.Source, out var sourceBuilder) ||
                !_entityBuilders.TryGetValue(association.Target, out var targetBuilder))
            {
                // data model misconfiguration (e.g. entity was removed from model, but not its associations)
                throw new InvalidOperationException("Discovered association that connects tables, missing from current model.");
            }

            // build metadata keys for association
            // (add fields used to define assocation to metadata)
            BuildAssociationMetadataKey(association, false);
            BuildAssociationMetadataKey(association, true);

            // Type of assocation on source side.
            // Nullable for nullable foreign key.
            var sourceType = targetBuilder.Type.Type.WithNullability(association.SourceMetadata.CanBeNull);

            // Type of association on target side.
            var tagetType = sourceBuilder.Type.Type;

            if (association.ManyToOne)
            {
                // for many-to-one assocations has collection type, defined by user preferences
                if (_options.DataModel.AssociationCollectionAsArray)
                {
                    tagetType = AST.ArrayType(tagetType, false);
                }
                else if (_dataModel.AssociationCollectionType != null)
                {
                    tagetType = _dataModel.AssociationCollectionType.WithTypeArguments(tagetType);
                }
                else
                {
                    // default type is IEnumerable
                    tagetType = WellKnownTypes.System.Collections.Generic.IEnumerable(tagetType);
                }
            }
            else             // if one-to-one association targets nullable columns, association is nullable
            {
                tagetType = tagetType.WithNullability(true);
            }

            // (if enabled) generate property-based association from source to target
            if (association.Property != null)
            {
                BuildAssociationProperty(
                    entityAssociations,
                    association.Source,
                    sourceType,
                    association.Property,
                    association.SourceMetadata);
            }

            // (if enabled) generate property-based back-reference association from target to source
            if (association.BackreferenceProperty != null)
            {
                BuildAssociationProperty(
                    entityAssociations,
                    association.Target,
                    tagetType,
                    association.BackreferenceProperty,
                    association.TargetMetadata);
            }

            // (if enabled) generate extension-based association from source to target
            if (association.Extension != null)
            {
                BuildAssociationExtension(
                    extensionEntityAssociations,
                    extensionAssociations,
                    sourceBuilder,
                    targetBuilder,
                    sourceType,
                    association.Extension,
                    association.SourceMetadata,
                    association,
                    false);
            }

            // (if enabled) generate extension-based back-reference association from target to source
            if (association.BackreferenceExtension != null)
            {
                BuildAssociationExtension(
                    extensionEntityAssociations,
                    extensionAssociations,
                    targetBuilder,
                    sourceBuilder,
                    tagetType,
                    association.BackreferenceExtension,
                    association.TargetMetadata,
                    association,
                    true);
            }
        }