Exemplo n.º 1
0
        private void InitializeLazyMembers()
        {
            // A property that is part of a "unified key" has multiple incoming associations
            _isUnified = new Lazy <bool>(
                () => IncomingAssociations.Count > 1);

            _lookupEntity = new Lazy <Entity>(
                () =>
            {
                // Detached properties are not lookup properties
                if (Entity == null)
                {
                    return(null);
                }

                // Is this property a TypeId or DescriptorId on the table?  If so, it's not a lookup property.
                if (DescriptorEntitySpecification.IsEdFiDescriptorEntity(Entity.Name) &&
                    PropertyName == Entity.Name + "Id")        // TODO: Embedded convention - Types/descriptor properties use entity name + "Id" suffix
                {
                    return(null);
                }

                var currentAssociation = IncomingAssociations.FirstOrDefault(
                    x =>
                    x.AssociationType == AssociationViewType.FromBase ||
                    x.AssociationType == AssociationViewType.OneToOneIncoming ||
                    x.AssociationType == AssociationViewType.ManyToOne

                    // Prevent processing self-recursive relationships with key unification on current property (prevent endless loop)
                    && !(x.IsSelfReferencing && PropertyName.EqualsIgnoreCase(
                             x.PropertyMappingByThisName[PropertyName]
                             .OtherProperty.PropertyName)));

                if (currentAssociation == null)
                {
                    return(null);
                }

                var currentThisProperty = this;

                while (currentAssociation != null)
                {
                    var otherProperty = currentAssociation.PropertyMappingByThisName[currentThisProperty.PropertyName]
                                        .OtherProperty;

                    if (ModelComparers.EntityProperty.Equals(currentThisProperty, otherProperty))
                    {
                        throw new Exception(
                            "Association property mapping endpoints refer to the same property.");
                    }

                    currentThisProperty = otherProperty;

                    // Stop looking if we've hit a lookup table (Type or Descriptor)
                    if (currentThisProperty.Entity.IsLookup)
                    {
                        break;
                    }

                    currentAssociation = otherProperty.IncomingAssociations.FirstOrDefault(
                        x =>
                        x.AssociationType == AssociationViewType.FromBase ||
                        x.AssociationType == AssociationViewType.OneToOneIncoming ||
                        x.AssociationType == AssociationViewType.ManyToOne &&
                        !(x.IsSelfReferencing && currentThisProperty.PropertyName.EqualsIgnoreCase(
                              x.PropertyMappingByThisName[
                                  currentThisProperty
                                  .PropertyName]
                              .OtherProperty
                              .PropertyName)));
                }

                return
                (currentThisProperty.Entity.IsLookup &&
                 currentThisProperty.Entity.Aggregate != Entity.Aggregate
                            ? currentThisProperty.Entity
                            : null);
            });
        }
Exemplo n.º 2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Entity"/> class with a name and a list of
        /// properties that are defined locally on the entity (and are not part of incoming associations).
        /// </summary>
        /// <param name="domainModel">The incoming <seealso cref="DomainModel"/></param>
        /// <param name="entityDefinition">The incoming <seealso cref="EntityDefinition"/></param>
        internal Entity(DomainModel domainModel, EntityDefinition entityDefinition)
        {
            DomainModel = domainModel;

            Schema = entityDefinition.Schema;
            Name   = entityDefinition.Name;

            TableNameByDatabaseEngine = new Dictionary <DatabaseEngine, string>(entityDefinition.TableNames);

            Description        = entityDefinition.Description?.Trim();
            IsAbstract         = entityDefinition.IsAbstract;
            IsDeprecated       = entityDefinition.IsDeprecated;
            DeprecationReasons = entityDefinition.DeprecationReasons;

            _locallyDefinedProperties = entityDefinition.LocallyDefinedProperties.Select(x => new EntityProperty(x))
                                        .ToList();

            _identifiers = entityDefinition.Identifiers.Select(x => new EntityIdentifier(x))
                           .ToReadOnlyList();

            // Assign entity references to the identifiers, properties
            _identifiers.ForEach(i => i.Entity = this);
            _locallyDefinedProperties.ForEach(p => p.Entity = this);

            _properties = new Lazy <IReadOnlyList <EntityProperty> >(
                () =>
            {
                // All properties, identifying ones first
                var properties =
                    IncomingAssociations.Where(a => a.IsIdentifying)
                    .SelectMany(x => x.ThisAssociationProperties.Cast <DomainPropertyBase>())
                    .Concat(_locallyDefinedProperties.Where(p => p.IsIdentifying))
                    .Concat(
                        IncomingAssociations.Where(a => !a.IsIdentifying)
                        .SelectMany(x => x.ThisAssociationProperties))
                    .Concat(_locallyDefinedProperties.Where(p => !p.IsIdentifying))
                    .ToList();

                var distinctProperties = properties
                                         .Distinct(ModelComparers.DomainPropertyNameOnly)
                                         .ToList()
                                         .AsReadOnly();

                // Return the distinct set of EntityProperty instances,
                // constructing new EntityProperty instances for the "winning" AssociationProperty
                var entityProperties = distinctProperties.Select(dp =>
                                                                 (dp as EntityProperty) ?? new EntityProperty(dp as AssociationProperty))
                                       .ToList();

                // Ensure back-references to the Entity are set
                entityProperties.ForEach(p => p.Entity = this);

                return(entityProperties);
            });

            _nonIdentifyingProperties = new Lazy <IReadOnlyList <EntityProperty> >(
                () =>
                Properties.Where(p => !p.IsIdentifying)
                .ToList()
                .AsReadOnly());

            _derivedEntities = new Lazy <Entity[]>(
                () =>
            {
                AssociationView[] associations;

                if (!DomainModel.AssociationViewsByEntityFullName.TryGetValue(FullName, out associations))
                {
                    return(new Entity[0]);
                }

                return(associations
                       .Where(x => x.AssociationType == AssociationViewType.ToDerived)
                       .Select(x => x.OtherEntity)
                       .ToArray());
            });

            _propertyByName = new Lazy <IReadOnlyDictionary <string, EntityProperty> >(
                () =>
                Properties.ToDictionary(x => x.PropertyName, x => x, StringComparer.InvariantCultureIgnoreCase));

            _primaryIdentifier = new Lazy <EntityIdentifier>(
                () =>
                _identifiers.SingleOrDefault(x => x.IsPrimary));

            _alternateIdentifiers = new Lazy <IReadOnlyList <EntityIdentifier> >(
                () =>
                _identifiers.Where(x => !x.IsPrimary)
                .ToList());

            _baseAssociation = new Lazy <AssociationView>(
                () =>
            {
                AssociationView[] associations;

                if (!DomainModel.AssociationViewsByEntityFullName.TryGetValue(FullName, out associations))
                {
                    return(null);
                }

                return(associations.SingleOrDefault(a => a.AssociationType == AssociationViewType.FromBase));
            });

            _isEntityExtension = new Lazy <bool>(
                () => EdFiStandardEntityAssociation != null);

            _extensions = new Lazy <Entity[]>(
                () =>
            {
                AssociationView[] associations;

                if (!DomainModel.AssociationViewsByEntityFullName.TryGetValue(FullName, out associations))
                {
                    return(new Entity[0]);
                }

                return(associations
                       .Where(x => x.AssociationType == AssociationViewType.ToExtension)
                       .Select(x => x.OtherEntity)
                       .ToArray());
            });

            _extensionAssociations = new Lazy <AssociationView[]>(
                () =>
            {
                AssociationView[] associations;

                if (!DomainModel.AssociationViewsByEntityFullName.TryGetValue(FullName, out associations))
                {
                    return(new AssociationView[0]);
                }

                return(associations
                       .Where(x => x.AssociationType == AssociationViewType.ToExtension)
                       .ToArray());
            });

            _aggregateExtensionOneToOnes = new Lazy <AssociationView[]>(
                () =>
            {
                return(NavigableOneToOnes.Where(a => a.ThisEntity.Schema != a.OtherEntity.Schema)
                       .ToArray());
            });

            _aggregateExtensionChildren = new Lazy <AssociationView[]>(
                () =>
            {
                return(NavigableChildren.Where(a => a.ThisEntity.Schema != a.OtherEntity.Schema)
                       .ToArray());
            });

            _edFiStandardEntity = new Lazy <Entity>(
                () =>
            {
                if (EdFiStandardEntityAssociation == null)
                {
                    return(null);
                }

                return(EdFiStandardEntityAssociation.OtherEntity);
            });

            _edFiStandardEntityAssociation = new Lazy <AssociationView>(
                () =>
                IncomingAssociations
                .SingleOrDefault(a => a.AssociationType == AssociationViewType.FromCore)
                );

            _childToAggregateRootIdentifierPropertyMappings =
                new Lazy <IReadOnlyList <PropertyMapping> >(() => BuildChildToAggregateRootPropertyMappings(this));
        }