/// <summary>
 /// Default constructor.
 /// </summary>
 public StatementSqlBuilderJoinInstruction(
     GenericStatementSqlBuilder sqlBuilder, 
     SqlJoinType joinType,
     FormattableString whereClause, 
     FormattableString orderClause)
 {
     this.SqlBuilder = sqlBuilder;
     this.JoinType = joinType;
     this.WhereClause = whereClause;
     this.OrderClause = orderClause;
 }
 /// <summary>
 ///     Default constructor.
 /// </summary>
 public StatementSqlBuilderJoinInstruction(
     GenericStatementSqlBuilder sqlBuilder,
     SqlJoinType joinType,
     FormattableString whereClause,
     FormattableString orderClause)
 {
     SqlBuilder  = sqlBuilder;
     JoinType    = joinType;
     WhereClause = whereClause;
     OrderClause = orderClause;
 }
Пример #3
0
        private void FindRelationship(
            GenericStatementSqlBuilder firstEntitySqlBuilder,
            GenericStatementSqlBuilder secondEntitySqlBuilder,
            out PropertyMapping[] firstEntityRelationshipPropertyMappings,
            out PropertyMapping[] secondEntityRelationshipPropertyMappings,
            ref SqlJoinType secondEntityJoinType)
        {
            var firstEntityMapping  = firstEntitySqlBuilder.EntityMapping;
            var secondEntityMapping = secondEntitySqlBuilder.EntityMapping;

            EntityMappingRelationship firstToSecondEntityMappingRelationship;
            EntityMappingRelationship secondToFirstEntityMappingRelationship;

            // two flags in order to cover 1-to-1 relationships
            bool firstToSecondParentChildRelationship;
            bool secondToFirstParentChildRelationship;

            this.FindRelationship(firstEntityMapping, secondEntityMapping, out firstToSecondEntityMappingRelationship, out firstToSecondParentChildRelationship);
            this.FindRelationship(secondEntityMapping, firstEntityMapping, out secondToFirstEntityMappingRelationship, out secondToFirstParentChildRelationship);

            if (firstToSecondEntityMappingRelationship == null && secondToFirstEntityMappingRelationship == null)
            {
                // no relationship was found on either side
                firstEntityRelationshipPropertyMappings  = null;
                secondEntityRelationshipPropertyMappings = null;
                return;
            }

            firstEntityRelationshipPropertyMappings  = firstToSecondEntityMappingRelationship?.ReferencingKeyProperties;
            secondEntityRelationshipPropertyMappings = secondToFirstEntityMappingRelationship?.ReferencingKeyProperties;

            // fix the lack of relationship info on one side, this is an acceptable scenario on parent entities only
            if (firstToSecondEntityMappingRelationship == null)
            {
                if (secondToFirstParentChildRelationship)
                {
                    // first * - 1 second
                    throw new InvalidOperationException($"Expected to find foreign keys on the '{firstEntityMapping.EntityType}' entity for the '{secondEntityMapping.EntityType}' entity");
                }
                else
                {
                    // first 1 - * second
                    firstEntityRelationshipPropertyMappings = firstEntitySqlBuilder.KeyProperties;
                    firstToSecondParentChildRelationship    = true;
                }
            }
            else if (secondToFirstEntityMappingRelationship == null)
            {
                if (firstToSecondParentChildRelationship)
                {
                    // second * - 1 first
                    throw new InvalidOperationException($"Expected to find foreign keys on the '{secondEntityMapping.EntityType}' entity for the '{firstEntityMapping.EntityType}' entity");
                }
                else
                {
                    // second 1 - * second
                    secondEntityRelationshipPropertyMappings = secondEntitySqlBuilder.KeyProperties;
                    secondToFirstParentChildRelationship     = true;
                }
            }

            if (firstEntityRelationshipPropertyMappings.Length != secondEntityRelationshipPropertyMappings.Length)
            {
                throw new InvalidOperationException($"Mismatch in the number of properties that are part of the relationship between '{firstEntityMapping.EntityType}' ({firstEntityRelationshipPropertyMappings.Length} properties) and '{secondEntityMapping.EntityType}' ({secondEntityRelationshipPropertyMappings.Length} properties)");
            }

            // in case the second entity is a child, one of its foreign key properties is not nullable and the join type wasn't specified, default to INNER JOIN
            if (secondEntityJoinType == SqlJoinType.NotSpecified && secondToFirstParentChildRelationship == false && secondEntityRelationshipPropertyMappings.Any(propMapping =>
            {
                var propType = propMapping.Descriptor.PropertyType;
                return
                (#if COREFX
                 propType.GetTypeInfo().IsValueType
#else
                 propType.IsValueType
#endif
                 && Nullable.GetUnderlyingType(propMapping.Descriptor.PropertyType) == null);
            }))
            {
                secondEntityJoinType = SqlJoinType.InnerJoin;
            }
        }