Exemple #1
0
        public void Find_RelatedAttributeAliasedEntity_MatchesExpected()
        {
            var entityReference = new EntityReference {
                EntityType = typeof(ChildRaisedRow)
            };
            var definitionProvider = new DataAnnotationsDefinitionProvider();
            var target             = new EntityDefinition(definitionProvider, entityReference);

            var relationReference = new EntityReference {
                EntityType = typeof(SubRow), EntityAlias = "SubEntity"
            };
            var attributeLocation = definitionProvider.GetEntityLocation(relationReference);
            var attributePath     = new LinkedList <EntityLocation>();

            attributePath.AddLast(attributeLocation);
            var expected = new EntityAttributeDefinition(
                attributePath,
                relationReference.EntityType.GetProperty(nameof(SubRow.FakeSubEntityId), BindingFlags.Public | BindingFlags.Instance),
                nameof(SubRow.FakeSubEntityId),
                EntityAttributeTypes.RelatedAutoNumberKey,
                1,
                $"SubEntity.{nameof(SubRow.FakeSubEntityId)}");

            var actual = target.Find(CreateExpression <ChildRaisedRow, int>(row => row.ComplexEntity.SubEntity.FakeSubEntityId));

            Assert.AreEqual(expected, actual, string.Join(Environment.NewLine, expected.GetDifferences(actual)));
        }
        /// <summary>
        /// Gets the base object for the attribute so that the correct POCO is targeted by the attribute delegate.
        /// </summary>
        /// <param name="item">
        /// The root-level POCO item.
        /// </param>
        /// <param name="attribute">
        /// The attribute to get the base object for.
        /// </param>
        /// <returns>
        /// The attribute's base <see cref="object"/>.
        /// </returns>
        private static object GetBaseObject(object item, EntityAttributeDefinition attribute)
        {
            var baseObject  = item;
            var currentNode = attribute.EntityNode.List.First;
            var targetNode  = attribute.EntityNode;

            while (currentNode != targetNode && currentNode?.Next != null && currentNode.Next.Value.IsVirtual == false)
            {
                var entityLocation = currentNode.Next.Value;

                // If the base object can't be found, the row has been flattened, so return the original item.
                baseObject  = GetObjectProperty(baseObject, entityLocation) ?? item;
                currentNode = currentNode.Next;
            }

            return(baseObject);
        }
        /// <summary>
        /// Gets the attributes for a relation.
        /// </summary>
        /// <param name="entityType">
        /// The entity type.
        /// </param>
        /// <returns>
        /// An <see cref="IEnumerable{T}"/> of <see cref="EntityAttributeDefinition"/> items for the <paramref name="entityType"/>.
        /// </returns>
        private IEnumerable <EntityAttributeDefinition> GetAttributeDefinitions(Type entityType)
        {
            var entityReference = new EntityReference
            {
                EntityType = entityType
            };

            var entityLocation = this.GetEntityLocation(entityReference);

            var entityPath = new LinkedList <EntityLocation>();

            entityPath.AddLast(entityLocation);

            var attributeReferences = this.GetAttributeReferences(entityType);

            foreach (var attributeReference in attributeReferences)
            {
                var physicalName   = this.GetPhysicalName(attributeReference.PropertyInfo);
                var ordinal        = this.GetOrdinal(attributeReference.PropertyInfo);
                var attributeName  = physicalName;
                var isPrimaryKey   = this.IsKey(attributeReference.PropertyInfo);
                var isIdentity     = this.IsIdentity(attributeReference.PropertyInfo);
                var isComputed     = this.IsComputed(attributeReference.PropertyInfo);
                var attributeTypes = EntityAttributeTypes.None;

                if (isPrimaryKey)
                {
                    attributeTypes |= EntityAttributeTypes.PrimaryKey;
                }

                if (isIdentity)
                {
                    attributeTypes |= EntityAttributeTypes.IdentityColumn;
                }

                if (isComputed)
                {
                    attributeTypes |= EntityAttributeTypes.Computed;
                }

                if (attributeReference.IsRelatedAttribute)
                {
                    attributeTypes |= EntityAttributeTypes.ExplicitRelatedAttribute;
                    var relatedEntityReference = new EntityReference
                    {
                        EntityType    = attributeReference.EntityReference.EntityType,
                        ContainerType = entityType,
                        EntityAlias   = attributeReference.EntityReference.EntityAlias
                    };

                    var relatedLocation = this.GetEntityLocation(relatedEntityReference);

                    // This is not a physical object on the POCO, so we indicate it as virtual.
                    relatedLocation.IsVirtual = true;

                    entityPath.AddLast(relatedLocation);

                    // Use the physical name if overridden.
                    physicalName = attributeReference.PhysicalName ?? physicalName;

                    var entityAttributeDefinition = new EntityAttributeDefinition(
                        entityPath,
                        attributeReference.PropertyInfo,
                        physicalName,
                        attributeTypes,
                        int.MaxValue,
                        attributeReference.PropertyInfo.Name == physicalName ? null : attributeReference.PropertyInfo.Name);

                    entityPath.RemoveLast();

                    yield return(entityAttributeDefinition);
                }
                else if (attributeReference.IsRelation)
                {
                    attributeTypes |= EntityAttributeTypes.Relation;

                    // Include the relation itself for quick access to getter/setter methods.
                    var entityAttributeDefinition = new EntityAttributeDefinition(
                        entityPath,
                        attributeReference.PropertyInfo,
                        attributeName,
                        attributeTypes,
                        ordinal,
                        attributeReference.Name);

                    yield return(entityAttributeDefinition);

                    foreach (var definition in this.GetAttributeDefinitions(entityPath, attributeReference.PropertyInfo))
                    {
                        yield return(definition);
                    }
                }
                else
                {
                    attributeTypes |= EntityAttributeTypes.DirectAttribute;
                    var entityAttributeDefinition = new EntityAttributeDefinition(
                        entityPath,
                        attributeReference.PropertyInfo,
                        attributeName,
                        attributeTypes,
                        ordinal);

                    yield return(entityAttributeDefinition);
                }
            }
        }
        /// <summary>
        /// Gets the entity definitions for the specified entity property.
        /// </summary>
        /// <param name="entityPath">
        /// The entity path.
        /// </param>
        /// <param name="entityProperty">
        /// The entity property to evaluate.
        /// </param>
        /// <returns>
        /// An <see cref="IEnumerable{T}"/> of <see cref="EntityAttributeDefinition"/> items.
        /// </returns>
        private IEnumerable <EntityAttributeDefinition> GetAttributeDefinitions(LinkedList <EntityLocation> entityPath, PropertyInfo entityProperty)
        {
            var entityType        = entityProperty.PropertyType;
            var relationReference = new EntityReference
            {
                EntityType    = entityType,
                ContainerType = entityPath.First?.Value.EntityType,
                EntityAlias   = entityProperty.Name
            };

            var relationLocation = this.GetEntityLocation(relationReference);

            entityPath.AddLast(relationLocation);

            var entityProperties = this.GetFilteredEntityProperties(entityType).ToList();

            // Do columns first.
            foreach (var propertyInfo in this.GetDirectPropertyInfos(entityProperties))
            {
                var propertyName  = propertyInfo.Name;
                var physicalName  = this.GetPhysicalName(propertyInfo);
                var propertyAlias = string.Concat(relationLocation.Alias ?? relationLocation.Name, '.', propertyName);
                var ordinal       = this.GetOrdinal(propertyInfo);
                var isPrimaryKey  = this.IsKey(propertyInfo);
                var isIdentity    = this.IsIdentity(propertyInfo);
                var isComputed    = this.IsComputed(propertyInfo);

                var attributeTypes = EntityAttributeTypes.RelatedAttribute;

                if (isPrimaryKey)
                {
                    attributeTypes |= EntityAttributeTypes.PrimaryKey;
                }

                if (isIdentity)
                {
                    attributeTypes |= EntityAttributeTypes.IdentityColumn;
                }

                if (isComputed)
                {
                    attributeTypes |= EntityAttributeTypes.Computed;
                }

                var entityAttributeDefinition = new EntityAttributeDefinition(
                    entityPath,
                    propertyInfo,
                    physicalName,
                    attributeTypes,
                    ordinal,
                    propertyName == propertyAlias ? null : propertyAlias);

                yield return(entityAttributeDefinition);
            }

            // Next, handle direct related entity attributes.
            foreach (var propertyInfo in this.GetRelatedColumnPropertyInfos(entityProperties))
            {
                var attributeReference = GetRelatedEntityAttributeReference(propertyInfo);

                // This is not a physical object on the POCO, so we indicate it as virtual.
                var relatedLocation = this.GetEntityLocation(attributeReference.EntityReference);
                relatedLocation.IsVirtual = true;

                entityPath.AddLast(relatedLocation);

                // Adding the dot avoids collisions with FKs.
                var propertyAlias = string.Concat(relationLocation.Alias ?? relationLocation.Name, '.', attributeReference.Name);

                var entityAttributeDefinition = new EntityAttributeDefinition(
                    entityPath,
                    propertyInfo,
                    attributeReference.PhysicalName,
                    EntityAttributeTypes.RelatedAttribute,
                    int.MaxValue,
                    attributeReference.Name == propertyAlias ? null : propertyAlias);

                entityPath.RemoveLast();

                yield return(entityAttributeDefinition);
            }

            foreach (var propertyInfo in this.GetRelationPropertyInfos(entityProperties))
            {
                var attributeName = this.GetPhysicalName(propertyInfo);

                // Include the relation itself for quick access to getter/setter methods.
                var relationAttribute = new EntityAttributeDefinition(
                    entityPath,
                    propertyInfo,
                    attributeName,
                    EntityAttributeTypes.Relation,
                    int.MaxValue,
                    propertyInfo.Name);

                yield return(relationAttribute);

                foreach (var entityAttributeDefinition in this.GetAttributeDefinitions(entityPath, propertyInfo))
                {
                    yield return(entityAttributeDefinition);
                }
            }

            entityPath.RemoveLast();
        }
Exemple #5
0
 /// <summary>
 /// Gets the canonical attribute name.
 /// </summary>
 /// <param name="attribute">
 /// The attribute to get the name for.
 /// </param>
 /// <returns>
 /// The physical name of the attribute, or the alias, if the attribute is aliased. <see cref="string"/>.
 /// </returns>
 private string GetAttributeCanonicalName(EntityAttributeDefinition attribute)
 {
     return(this.Escape(attribute.Alias ?? attribute.PhysicalName));
 }
Exemple #6
0
 /// <inheritdoc />
 public string GetCanonicalName(EntityAttributeDefinition attribute)
 {
     return($"{this.GetPhysicalName(attribute.Entity)}.{this.GetAttributeCanonicalName(attribute)}");
 }
Exemple #7
0
 /// <inheritdoc />
 public string GetReferenceName(EntityAttributeDefinition attribute)
 {
     return($"{this.GetEntityCanonicalName(attribute.Entity)}.{this.Escape(attribute.PhysicalName)}");
 }
Exemple #8
0
 /// <inheritdoc />
 public string Qualify(EntityAttributeDefinition attribute, EntityLocation entityLocation)
 {
     return($"{this.GetEntityCanonicalName(entityLocation)}.{this.GetAttributeCanonicalName(attribute)}");
 }
Exemple #9
0
 /// <inheritdoc />
 public string Qualify(EntityAttributeDefinition attribute)
 {
     return(this.Qualify(attribute, attribute.Entity));
 }