/// <summary> /// Initializes a new instance of the <see cref="AggregateExtension" /> class using the supplied extension entity names. /// </summary> public AggregateExtension(DomainModel domainModel, AggregateExtensionDefinition aggregateExtensionDefinition) { _domainModel = domainModel; AggregateRootEntityName = aggregateExtensionDefinition.AggregateRootEntityName; ExtensionEntityNames = aggregateExtensionDefinition.ExtensionEntityNames; }
internal Aggregate(DomainModel domainModel, AggregateDefinition aggregateDefinition) { DomainModel = domainModel; FullName = aggregateDefinition.AggregateRootEntityName; var memberEntityNames = new[] { aggregateDefinition.AggregateRootEntityName } .Concat(aggregateDefinition.AggregateEntityNames) .Distinct() .ToArray(); Name = aggregateDefinition.AggregateRootEntityName.Name; MemberEntityNames = memberEntityNames; }
internal Association(DomainModel domainModel, AssociationDefinition associationDefinition) { if (associationDefinition.PrimaryEntityProperties.Length != associationDefinition.SecondaryEntityProperties.Length) { throw new Exception("The association definition is invalid because a different number of properties were provided for the primary and secondary ends of the association."); } _domainModel = domainModel; FullName = associationDefinition.FullName; var primaryEntityAssociationProperties = associationDefinition.PrimaryEntityProperties .Select(x => new AssociationProperty(x)) .ToArray(); // Identifying associations mean that the properties in the receiving entity must also be identifying if (associationDefinition.IsIdentifying) { // Coerce each secondary entity property definition to be identifying associationDefinition.SecondaryEntityProperties.ForEach(p => p.IsIdentifying = true); } var secondaryEntityAssociationProperties = associationDefinition.SecondaryEntityProperties .Select(x => new AssociationProperty(x)) .ToArray(); Cardinality = associationDefinition.Cardinality; PrimaryEntityFullName = associationDefinition.PrimaryEntityFullName; SecondaryEntityFullName = associationDefinition.SecondaryEntityFullName; _primaryEntityAssociationProperties = new Lazy <AssociationProperty[]>( () => { Entity primaryEntity; if (!_domainModel.EntityByFullName.TryGetValue(PrimaryEntityFullName, out primaryEntity)) { throw new Exception($"The primary entity '{PrimaryEntityFullName}' could not be found."); } primaryEntityAssociationProperties.ForEach(p => p.Entity = primaryEntity); return(primaryEntityAssociationProperties); }); _secondaryEntityAssociationProperties = new Lazy <AssociationProperty[]>( () => { Entity secondaryEntity; if (!_domainModel.EntityByFullName.TryGetValue(SecondaryEntityFullName, out secondaryEntity)) { throw new Exception($"The secondary entity '{SecondaryEntityFullName}' could not be found."); } secondaryEntityAssociationProperties.ForEach(p => p.Entity = secondaryEntity); return(secondaryEntityAssociationProperties); }); IsIdentifying = associationDefinition.IsIdentifying; IsRequired = associationDefinition.IsRequired; IsRequiredCollection = associationDefinition.Cardinality == Cardinality.OneToOneOrMore; ConstraintByDatabaseEngine = associationDefinition.ConstraintNames; }
/// <summary> /// Constructor that takes a set of DomainModelDefinitions to initialize it values /// </summary> /// <param name="domainModelDefinitions"></param> public DomainModelBuilder(IEnumerable <DomainModelDefinitions> domainModelDefinitions) { _domainModel = new DomainModel(); domainModelDefinitions.ForEach(x => _domainModel.AddDomainModelDefinitions(x)); }
/// <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)); }
internal AssociationView(DomainModel domainModel, Association association, bool isPrimaryEntity) { _domainModel = domainModel; Association = association; _isPrimaryEntity = isPrimaryEntity; _thisProperties = new Lazy <EntityProperty[]>( () => _thisAssociationProperties.Value.Select(ap => ap.EntityProperty).ToArray()); _otherProperties = new Lazy <EntityProperty[]>( () => _otherAssociationProperties.Value.Select(ap => ap.EntityProperty).ToArray()); _thisAssociationProperties = new Lazy <AssociationProperty[]>( () => { InitializeAssociationPropertyEntityBackReferences(); return(_isPrimaryEntity ? association.PrimaryEntityAssociationProperties : association.SecondaryEntityAssociationProperties); }); _otherAssociationProperties = new Lazy <AssociationProperty[]>( () => { InitializeAssociationPropertyEntityBackReferences(); return(_isPrimaryEntity ? association.SecondaryEntityAssociationProperties : association.PrimaryEntityAssociationProperties); }); _propertyMappings = new Lazy <IReadOnlyList <PropertyMapping> >( () => _thisProperties.Value.Select((p, i) => new PropertyMapping(p, _otherProperties.Value[i])) .ToList()); _propertyMappingsByThisName = new Lazy <IReadOnlyDictionary <string, PropertyMapping> >( () => new ReadOnlyDictionary <string, PropertyMapping>( _propertyMappings.Value.ToDictionary( m => m.ThisProperty.PropertyName, m => m, StringComparer.InvariantCultureIgnoreCase))); _propertyMappingsByOtherName = new Lazy <IReadOnlyDictionary <string, PropertyMapping> >( () => new ReadOnlyDictionary <string, PropertyMapping>( _propertyMappings.Value.ToDictionary( m => m.OtherProperty.PropertyName, m => m, StringComparer.InvariantCultureIgnoreCase))); _foreignKeyNameParts = new Lazy <ForeignKeyNameParts>( () => GetForeignKeyNameParts(this)); _isSoftDependency = new Lazy <bool>( () => { // Navigable relationships do not span aggregates and do not represent aggregate dependencies if (IsNavigable) { return(false); } bool isContainingEntityPresenceOptional = ThisEntity.AncestorsOrSelf.Select(e => e.ParentAssociation) // Exclude root's ParentAssociation (which will be null) .Where(av => av != null) .Any(av => // An optional collection (av.AssociationType == AssociationViewType.ManyToOne && !av.Association.IsRequiredCollection) // An optional incoming one-to-one reference || (av.AssociationType == AssociationViewType.OneToOneIncoming && !av.IsRequired)); if (isContainingEntityPresenceOptional) { return(true); } // Containing entity is required, so evaluate the reference itself if (AssociationType == AssociationViewType.ManyToOne || AssociationType == AssociationViewType.OneToOneIncoming) { return(!IsRequired); } // All other associations do not represent dependencies return(false); }); }