Exemplo n.º 1
0
 private static void ValidateReferenceModeNamingChanged(ReferenceModeNamingCustomizesObjectType referenceModeNamingCustomizesObjectType)
 {
     if (null != referenceModeNamingCustomizesObjectType)
     {
         ORMCore.ObjectType objectType = referenceModeNamingCustomizesObjectType.ObjectType;
         if (objectType != null)
         {
             ConceptType conceptType = ConceptTypeIsForObjectType.GetConceptType(objectType);
             if (null == conceptType)
             {
                 foreach (ORMCore.Role role in objectType.PlayedRoleCollection)
                 {
                     foreach (ConceptTypeChild conceptTypeChild in ConceptTypeChildHasPathFactType.GetConceptTypeChild(role.FactType))
                     {
                         ValidateConceptTypeChildNameChanged(conceptTypeChild);
                     }
                 }
             }
             else
             {
                 ValidateConceptTypeNameChanged(conceptType);
             }
         }
     }
 }
        /// <summary>
        /// for regular relationships
        /// </summary>
        /// <param name="relation"></param>
        /// <param name="source"></param>
        /// <param name="target"></param>
        /// <param name="notifyAdded"></param>
        /// <param name="associationCounter"></param>
        /// <returns></returns>
        private static bool CreateBinaryAssociation(ConceptTypeChild relation, ConceptType source, ConceptType target, INotifyElementAdded notifyAdded, ref int associationCounter)
        {
            if (BinaryAssociationHasConceptTypeChild.GetBinaryAssociation(relation).Count > 0)
            {
                //it has already been created
                return(true);
            }
            else if (EntityTypeIsPrimarilyForConceptType.GetEntityType(target) != null)
            {
                #region create association
                BinaryAssociation b = new BinaryAssociation(relation.Store,
                                                            new PropertyAssignment[] { new PropertyAssignment(BinaryAssociation.NumberDomainPropertyId, associationCounter++) });
                //new BinaryAssociationHasConceptTypeChild(b, relation);
                BinaryAssociationHasConceptTypeChild.GetConceptTypeChildPath(b).Add(relation);

                Role r1 = new Role(relation.Store,
                                   new PropertyAssignment[] { new PropertyAssignment(Role.PredicateTextDomainPropertyId, source.Name) });

                Role r2 = new Role(relation.Store,
                                   new PropertyAssignment[] { new PropertyAssignment(Role.PredicateTextDomainPropertyId, target.Name) });

                b.RoleCollection.Add(r1);
                b.RoleCollection.Add(r2);

                EntityType sourceEntity = EntityTypeIsPrimarilyForConceptType.GetEntityType(source);
                EntityType targetEntity = EntityTypeIsPrimarilyForConceptType.GetEntityType(target);
                sourceEntity.RoleCollection.Add(r1);
                targetEntity.RoleCollection.Add(r2);
                sourceEntity.BarkerErModel.BinaryAssociationCollection.Add(b);
                #endregion

                //determine whether roles are mandatory or optional
                List <ConceptTypeChild> links = new List <ConceptTypeChild>(1);
                links.Add(relation);
                r1.IsMandatory = AllStepsMandatory(targetEntity, links);
                if (relation is ConceptTypeAssimilatesConceptType)
                {
                    r2.IsMandatory = AllStepsMandatory(sourceEntity, links);
                }

                #region determine whether roles are multivalued or not - and possibly rename
                ORMCore.ObjectType           sourceObjectType = ConceptTypeIsForObjectType.GetObjectType(source);
                ORMCore.ObjectType           targetObjectType = ConceptTypeIsForObjectType.GetObjectType(target);
                ORMCore.UniquenessConstraint uSource = null, uTarget = null;
                foreach (ORMCore.FactType factType in ConceptTypeChildHasPathFactType.GetPathFactTypeCollection(relation))
                {
                    Debug.Assert(factType.RoleCollection.Count == 2, "Error when mapping to Barker ER; the fact type is not binary");
                    foreach (ORMCore.RoleBase r in factType.RoleCollection)
                    {
                        //need to use RoleBase because we might run into RoleProxy
                        ORMCore.Role role = r.Role;
                        foreach (ORMCore.ConstraintRoleSequence constraintRoleSequence in role.ConstraintRoleSequenceCollection)
                        {
                            ORMCore.UniquenessConstraint uninquenessConstraint = constraintRoleSequence as ORMCore.UniquenessConstraint;
                            if (uninquenessConstraint != null &&                                        //check that it's a uniqueness constraint
                                uninquenessConstraint.Modality == ORMCore.ConstraintModality.Alethic && //check it's alethic
                                uninquenessConstraint.IsInternal)                                       //check it's internal
                            {
                                if (role.RolePlayer == sourceObjectType)
                                {
                                    uSource = uninquenessConstraint;
                                }
                                if (role.RolePlayer == targetObjectType)
                                {
                                    uTarget = uninquenessConstraint;
                                }
                            }
                        }
                    }
                    //name the roles properly
                    //TODO this is a hack; proper name generation is yet to be implemented
                    foreach (ORMCore.ReadingOrder order in factType.ReadingOrderCollection)
                    {
                        string text  = order.ReadingText;
                        int    first = text.IndexOf('}') + 1;
                        text = text.Substring(first, text.LastIndexOf('{') - first);
                        text = text.Trim();

                        if (!string.IsNullOrEmpty(text) &&
                            order.RoleCollection != null && order.RoleCollection.Count > 0 &&
                            order.RoleCollection[0].Role != null)
                        {
                            ORMCore.ObjectType o = order.RoleCollection[0].Role.RolePlayer;
                            if (o == sourceObjectType)
                            {
                                r1.PredicateText = text;
                            }
                            else if (o == targetObjectType)
                            {
                                r2.PredicateText = text;
                            }
                        }
                    }
                }
                if (uSource != null && uSource == uTarget)
                {
                    //it's many-to-many
                    r1.IsMultiValued = true;
                    r2.IsMultiValued = true;
                }
                else if (uSource == null || uTarget == null)
                {
                    //it's one-to-many
                    r1.IsMultiValued = uSource != null;
                    r2.IsMultiValued = uTarget != null;
                }
                else if (uSource != null && uTarget != null)
                {
                    //it's one-to-one
                    r1.IsMultiValued = false;
                    r2.IsMultiValued = false;
                }
                else
                {
                    Debug.Fail("Found a fact type with no uniqueness constraints!");
                }
                #endregion

                #region primary id?
                foreach (Uniqueness u in UniquenessIncludesConceptTypeChild.GetUniquenessCollection(relation))
                {
                    if (u.IsPreferred)
                    {
                        r1.IsPrimaryIdComponent = true;
                        break;
                    }
                }
                #endregion

                //notify elements added
                if (notifyAdded != null)
                {
                    notifyAdded.ElementAdded(b, true);
                    notifyAdded.ElementAdded(r1, true);
                    notifyAdded.ElementAdded(r2, true);
                }

                return(true);
            }
            else
            {
                //should not create binary association in this case
                return(false);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Check if two data types can be compared. This is a weaker check
        /// than <see cref="IsAssignableValueType"/> in that it does not
        /// do any facet checking to see if one value can store the only,
        /// but only checks if the two can be compared.
        /// </summary>
        /// <param name="valueType1">The first value type to compare.</param>
        /// <param name="valueType2">The second value type to compare.</param>
        /// <param name="equalityOnly">Set to true if the equality or inequality
        /// of the two values is required, but an ordered check is not.</param>
        /// <returns><see langword="true"/> if the two types can be compared.</returns>
        public static bool IsComparableValueType(ObjectType valueType1, ObjectType valueType2, bool equalityOnly)
        {
            DataType dataType1 = valueType1.DataType;
            DataType dataType2 = valueType2.DataType;

            if (dataType1 == dataType2)
            {
                switch (dataType1.PortableDataType)
                {
                case PortableDataType.Unspecified:
                    // Give the user the benefit of the doubt that fixing the
                    // unspecified data type will result in comparable values.
                    return(true);

                case PortableDataType.NumericAutoCounter:
                    // Only support this if the value types are the same. Otherwise, we're mapping different
                    // counters to each other, which is meaningless.
                    return(valueType1 == valueType2);

                default:
                    return(dataType1.CanCompare && (equalityOnly || (dataType1.RangeSupport != DataTypeRangeSupport.None)));
                }
            }
            else if (dataType1.CanCompare &&
                     dataType2.CanCompare &&
                     (equalityOnly || (dataType1.RangeSupport != DataTypeRangeSupport.None && dataType2.RangeSupport != DataTypeRangeSupport.None)))
            {
                // Look at specific types.
                PortableDataType targetType = dataType1.PortableDataType;
                PortableDataType sourceType = dataType2.PortableDataType;
                if (sourceType == PortableDataType.Unspecified)
                {
                    // Give user the benefit of the doubt that the types will be made comparable
                    // if this choice is made.
                    return(true);
                }
                switch (targetType)
                {
                case PortableDataType.Unspecified:
                    // Let user fix
                    return(true);

                case PortableDataType.TextFixedLength:
                case PortableDataType.TextVariableLength:
                case PortableDataType.TextLargeLength:
                    switch (sourceType)
                    {
                    case PortableDataType.TextFixedLength:
                    case PortableDataType.TextVariableLength:
                    case PortableDataType.TextLargeLength:
                        return(true);
                    }
                    break;

                case PortableDataType.NumericSignedInteger:
                case PortableDataType.NumericSignedSmallInteger:
                case PortableDataType.NumericSignedLargeInteger:
                case PortableDataType.NumericUnsignedInteger:
                case PortableDataType.NumericUnsignedTinyInteger:
                case PortableDataType.NumericUnsignedSmallInteger:
                case PortableDataType.NumericUnsignedLargeInteger:
                case PortableDataType.NumericFloatingPoint:
                case PortableDataType.NumericSinglePrecisionFloatingPoint:
                case PortableDataType.NumericDoublePrecisionFloatingPoint:
                case PortableDataType.NumericDecimal:
                case PortableDataType.NumericMoney:
                    switch (sourceType)
                    {
                    case PortableDataType.NumericSignedInteger:
                    case PortableDataType.NumericSignedSmallInteger:
                    case PortableDataType.NumericSignedLargeInteger:
                    case PortableDataType.NumericUnsignedInteger:
                    case PortableDataType.NumericUnsignedTinyInteger:
                    case PortableDataType.NumericUnsignedSmallInteger:
                    case PortableDataType.NumericUnsignedLargeInteger:
                    case PortableDataType.NumericFloatingPoint:
                    case PortableDataType.NumericSinglePrecisionFloatingPoint:
                    case PortableDataType.NumericDoublePrecisionFloatingPoint:
                    case PortableDataType.NumericDecimal:
                    case PortableDataType.NumericMoney:
                        return(true);
                    }
                    break;
                //case PortableDataType.RawDataFixedLength:
                //case PortableDataType.RawDataVariableLength:
                //case PortableDataType.RawDataLargeLength:
                //case PortableDataType.RawDataPicture:
                //case PortableDataType.RawDataOleObject:
                // Raw data types are not comparable, these cases would form a dead code path.

                //case PortableDataType.NumericAutoCounter:
                //case PortableDataType.TemporalTime:
                //case PortableDataType.TemporalDate:
                //case PortableDataType.OtherRowId:
                //case PortableDataType.OtherObjectId:
                // These compare only to themselves, will be caught in first if block

                case PortableDataType.TemporalAutoTimestamp:
                case PortableDataType.TemporalDateAndTime:
                    switch (sourceType)
                    {
                    case PortableDataType.TemporalAutoTimestamp:
                    case PortableDataType.TemporalDateAndTime:
                        return(true);
                    }
                    break;

                case PortableDataType.LogicalTrueOrFalse:
                case PortableDataType.LogicalYesOrNo:
                    switch (sourceType)
                    {
                    case PortableDataType.LogicalTrueOrFalse:
                    case PortableDataType.LogicalYesOrNo:
                        return(true);
                    }
                    break;
                }
            }
            return(false);
        }
Exemplo n.º 4
0
            /// <summary>
            /// Binarizes the unary <see cref="FactType"/> specified by <paramref name="unaryFactType"/>, defaulting
            /// to using open-world assumption. The caller is responsible for making sure <paramref name="unaryFactType"/>
            /// is in fact a unary fact type.
            /// </summary>
            public static void BinarizeUnary(FactType unaryFactType, INotifyElementAdded notifyAdded)
            {
                Partition partition = unaryFactType.Partition;
                Store     store     = partition.Store;
                IHasAlternateOwner <FactType>      toAlternateOwner;
                IAlternateElementOwner <FactType>  alternateFactTypeOwner = (null == (toAlternateOwner = unaryFactType as IHasAlternateOwner <FactType>)) ? null : toAlternateOwner.AlternateOwner;
                LinkedElementCollection <RoleBase> roleCollection         = unaryFactType.RoleCollection;

                Debug.Assert(roleCollection.Count == 1, "Unaries should only have one role.");

                Role   unaryRole = (Role)roleCollection[0];
                string implicitBooleanValueTypeName = GetImplicitBooleanValueTypeName(unaryRole);

                // UNDONE: We are using open-world assumption now
                // Setup the mandatory constraint (for closed-world assumption)
                //MandatoryConstraint mandatoryConstraint = MandatoryConstraint.CreateSimpleMandatoryConstraint(unaryRole);
                //mandatoryConstraint.Model = unaryFactType.Model;
                //if (notifyAdded != null)
                //{
                //    notifyAdded.ElementAdded(mandatoryConstraint, true);
                //}

                // Setup the uniqueness constraint (to make the newly binarized FactType valid)
                if (unaryRole.SingleRoleAlethicUniquenessConstraint == null)
                {
                    UniquenessConstraint uniquenessConstraint = UniquenessConstraint.CreateInternalUniquenessConstraint(unaryFactType);
                    uniquenessConstraint.RoleCollection.Add(unaryRole);
                    if (notifyAdded != null)
                    {
                        notifyAdded.ElementAdded(uniquenessConstraint, true);
                    }
                }

                // Setup the boolean role (to make the FactType a binary)
                Role implicitBooleanRole = new Role(partition, null);

                implicitBooleanRole.Name = unaryRole.Name;

                // Setup the boolean value type (because the boolean role needs a role player)

                IAlternateElementOwner <ObjectType> alternateObjectTypeOwner = null;
                DomainClassInfo alternateCtor =
                    (null != alternateFactTypeOwner &&
                     null != (alternateObjectTypeOwner = alternateFactTypeOwner as IAlternateElementOwner <ObjectType>)) ?
                    alternateObjectTypeOwner.GetOwnedElementClassInfo(typeof(ObjectType)) :
                    null;
                PropertyAssignment implicitBooleanProperty  = new PropertyAssignment(ObjectType.IsImplicitBooleanValueDomainPropertyId, true);
                ObjectType         implicitBooleanValueType = (alternateCtor != null) ?
                                                              (ObjectType)partition.ElementFactory.CreateElement(alternateCtor, implicitBooleanProperty) :
                                                              new ObjectType(partition, implicitBooleanProperty);
                Dictionary <object, object> contextInfo = store.TransactionManager.CurrentTransaction.TopLevelTransaction.Context.ContextInfo;
                object duplicateNamesKey         = ORMModel.AllowDuplicateNamesKey;
                bool   removeDuplicateNamesKey   = false;
                object duplicateSignaturesKey    = ORMModel.BlockDuplicateReadingSignaturesKey;
                bool   addDuplicateSignaturesKey = false;

                try
                {
                    if (!contextInfo.ContainsKey(duplicateNamesKey))
                    {
                        contextInfo[duplicateNamesKey] = null;
                        removeDuplicateNamesKey        = true;
                    }
                    if (contextInfo.ContainsKey(duplicateSignaturesKey))
                    {
                        contextInfo[duplicateSignaturesKey] = null;
                        addDuplicateSignaturesKey           = true;
                    }
                    implicitBooleanValueType.Name = implicitBooleanValueTypeName;
                    if (alternateCtor != null)
                    {
                        ((IHasAlternateOwner <ObjectType>)implicitBooleanValueType).AlternateOwner = alternateObjectTypeOwner;
                    }
                    else
                    {
                        implicitBooleanValueType.Model = unaryFactType.ResolvedModel;
                    }
                    if (notifyAdded != null)
                    {
                        notifyAdded.ElementAdded(implicitBooleanValueType, true);
                    }
                }
                finally
                {
                    if (removeDuplicateNamesKey)
                    {
                        contextInfo.Remove(duplicateNamesKey);
                    }
                    if (addDuplicateSignaturesKey)
                    {
                        contextInfo[duplicateSignaturesKey] = null;
                    }
                }
                implicitBooleanValueType.DataType = store.ElementDirectory.FindElements <TrueOrFalseLogicalDataType>(false)[0];

                // Set value constraint on implicit boolean ValueType for open-world assumption
                ValueTypeValueConstraint implicitBooleanValueConstraint = implicitBooleanValueType.ValueConstraint
                                                                              = new ValueTypeValueConstraint(partition, null);

                // Add the true-only ValueRange to the value constraint for open-world assumption
                implicitBooleanValueConstraint.ValueRangeCollection.Add(new ValueRange(partition,
                                                                                       new PropertyAssignment(ValueRange.MinValueDomainPropertyId, bool.TrueString),
                                                                                       new PropertyAssignment(ValueRange.MaxValueDomainPropertyId, bool.TrueString)));

                // Make the boolean value type the role player for the implicit boolean role
                implicitBooleanRole.RolePlayer = implicitBooleanValueType;

                // Add the boolean role to the FactType
                roleCollection.Add(implicitBooleanRole);
                if (notifyAdded != null)
                {
                    notifyAdded.ElementAdded(implicitBooleanRole, true);
                }
            }
Exemplo n.º 5
0
        /// <summary>
        /// Test if an instance of one value type can be always be assigned to
        /// an instance of another value type.
        /// </summary>
        /// <param name="targetValueType">The type of the value being assigned to.</param>
        /// <param name="sourceValueType">The type of the value being assigned from.</param>
        /// <returns><see langword="true"/> if the source value can be assigned to the target value.</returns>
        /// <remarks>If either data type is unspecified, then the assumption is made that there is an error
        /// for this condition elsewhere and that the user will fix it, so this method returns true in these
        /// cases. Autogenerated values are assumed to be incompatible if they come from different value types
        /// because assigning autogenerated values to each other is also meaningingless.</remarks>
        public static bool IsAssignableValueType(ObjectType targetValueType, ObjectType sourceValueType)
        {
            if (targetValueType == sourceValueType)
            {
                return(true);
            }
            ValueTypeHasDataType targetUse;
            ValueTypeHasDataType sourceUse;

            if (null == (targetUse = ValueTypeHasDataType.GetLinkToDataType(targetValueType)) ||
                null == (sourceUse = ValueTypeHasDataType.GetLinkToDataType(sourceValueType)))
            {
                return(false);
            }
            PortableDataType targetType = targetUse.DataType.PortableDataType;
            PortableDataType sourceType = sourceUse.DataType.PortableDataType;

            if (sourceType == PortableDataType.Unspecified)
            {
                // Give user the benefit of the doubt that the types will be made compatible
                // if this choice is made.
                return(true);
            }
            int targetLength;
            int sourceLength;
            int targetScale;
            int sourceScale;

            switch (targetType)
            {
            case PortableDataType.Unspecified:
                // Let user fix
                return(true);

            case PortableDataType.TextFixedLength:
            case PortableDataType.TextVariableLength:
            case PortableDataType.TextLargeLength:
                switch (sourceType)
                {
                case PortableDataType.TextFixedLength:
                case PortableDataType.TextVariableLength:
                case PortableDataType.TextLargeLength:
                    targetLength = targetUse.Length;
                    sourceLength = sourceUse.Length;
                    return((targetLength == 0 ? int.MaxValue : targetLength) >= (sourceLength == 0 ? int.MaxValue : sourceLength));
                }
                break;

            case PortableDataType.NumericSignedInteger:
                switch (sourceType)
                {
                case PortableDataType.NumericSignedInteger:
                case PortableDataType.NumericSignedSmallInteger:
                    return(true);

                case PortableDataType.NumericDecimal:
                    if (sourceUse.Scale == 0)
                    {
                        sourceLength = sourceUse.Length;
                        if (sourceLength != 0 && sourceLength <= 9)                                         // 10 might be too big
                        {
                            return(true);
                        }
                    }
                    break;
                }
                break;

            case PortableDataType.NumericSignedSmallInteger:
                switch (sourceType)
                {
                case PortableDataType.NumericSignedSmallInteger:
                    return(true);

                case PortableDataType.NumericDecimal:
                    if (sourceUse.Scale == 0)
                    {
                        sourceLength = sourceUse.Length;
                        if (sourceLength != 0 && sourceLength <= 4)                                         // 5 might be too big
                        {
                            return(true);
                        }
                    }
                    break;
                }
                break;

            case PortableDataType.NumericSignedLargeInteger:
                switch (sourceType)
                {
                case PortableDataType.NumericSignedInteger:
                case PortableDataType.NumericSignedSmallInteger:
                case PortableDataType.NumericSignedLargeInteger:
                    return(true);

                case PortableDataType.NumericDecimal:
                    if (sourceUse.Scale == 0)
                    {
                        sourceLength = sourceUse.Length;
                        if (sourceLength != 0 && sourceLength <= 18)                                         // 19 might be too big
                        {
                            return(true);
                        }
                    }
                    break;
                }
                break;

            case PortableDataType.NumericUnsignedInteger:
                switch (sourceType)
                {
                case PortableDataType.NumericUnsignedInteger:
                case PortableDataType.NumericUnsignedTinyInteger:
                case PortableDataType.NumericUnsignedSmallInteger:
                    return(true);
                }
                break;

            case PortableDataType.NumericUnsignedTinyInteger:
                switch (sourceType)
                {
                case PortableDataType.NumericUnsignedTinyInteger:
                    return(true);
                }
                break;

            case PortableDataType.NumericUnsignedSmallInteger:
                switch (sourceType)
                {
                case PortableDataType.NumericUnsignedTinyInteger:
                case PortableDataType.NumericUnsignedSmallInteger:
                    return(true);
                }
                break;

            case PortableDataType.NumericUnsignedLargeInteger:
                switch (sourceType)
                {
                case PortableDataType.NumericUnsignedInteger:
                case PortableDataType.NumericUnsignedTinyInteger:
                case PortableDataType.NumericUnsignedSmallInteger:
                case PortableDataType.NumericUnsignedLargeInteger:
                    return(true);
                }
                break;

            //case PortableDataType.NumericAutoCounter:
            // Only support this if the value types are the same. Otherwise, we're mapping different
            // counters to each other, which is meaningless.
            case PortableDataType.NumericFloatingPoint:
            case PortableDataType.NumericSinglePrecisionFloatingPoint:
            case PortableDataType.NumericDoublePrecisionFloatingPoint:
                switch (sourceType)
                {
                case PortableDataType.NumericFloatingPoint:
                    sourceLength = sourceUse.Length;
                    if (sourceLength == 0)
                    {
                        sourceLength = 53;
                    }
                    break;

                case PortableDataType.NumericSinglePrecisionFloatingPoint:
                    sourceLength = 24;
                    break;

                case PortableDataType.NumericDoublePrecisionFloatingPoint:
                    sourceLength = 53;
                    break;

                default:
                    sourceLength = -1;
                    break;
                }
                if (sourceLength != -1)
                {
                    switch (targetType)
                    {
                    case PortableDataType.NumericSinglePrecisionFloatingPoint:
                        targetLength = 24;
                        break;

                    case PortableDataType.NumericDoublePrecisionFloatingPoint:
                        targetLength = 53;
                        break;

                    //case PortableDataType.NumericFloatingPoint:
                    default:
                        targetLength = targetUse.Length;
                        if (targetLength == 0)
                        {
                            targetLength = 53;
                        }
                        break;
                    }
                    if (targetLength >= sourceLength)
                    {
                        return(true);
                    }
                }
                break;

            case PortableDataType.NumericDecimal:
            case PortableDataType.NumericMoney:
                sourceScale = 0;
                switch (sourceType)
                {
                case PortableDataType.NumericDecimal:
                    sourceLength = sourceUse.Length;
                    if (sourceLength == 0)
                    {
                        sourceLength = 18;
                    }
                    else
                    {
                        sourceScale = sourceUse.Scale;
                    }
                    break;

                case PortableDataType.NumericMoney:
                    sourceLength = 19;
                    sourceScale  = 4;
                    break;

                case PortableDataType.NumericSignedInteger:
                case PortableDataType.NumericUnsignedInteger:
                    sourceLength = 10;
                    break;

                case PortableDataType.NumericSignedSmallInteger:
                case PortableDataType.NumericUnsignedSmallInteger:
                    sourceLength = 5;
                    break;

                case PortableDataType.NumericSignedLargeInteger:
                    sourceLength = 19;
                    break;

                case PortableDataType.NumericUnsignedLargeInteger:
                    sourceLength = 20;
                    break;

                case PortableDataType.NumericUnsignedTinyInteger:
                    sourceLength = 3;
                    break;

                default:
                    sourceLength = -1;
                    break;
                }
                if (sourceLength != -1)
                {
                    if (targetType == PortableDataType.NumericMoney)
                    {
                        targetLength = 19;
                        targetScale  = 4;
                    }
                    else
                    {
                        targetLength = targetUse.Length;                                 // Length maps to precision, verify precision first, then scale
                        if (targetLength == 0)
                        {
                            targetLength = 18;
                            targetScale  = 0;
                        }
                        else
                        {
                            targetScale = targetUse.Scale;
                        }
                    }
                    if (targetLength >= sourceLength && targetScale >= sourceScale)
                    {
                        return(true);
                    }
                }
                break;

            case PortableDataType.RawDataFixedLength:
            case PortableDataType.RawDataVariableLength:
            case PortableDataType.RawDataLargeLength:
                switch (sourceType)
                {
                case PortableDataType.RawDataFixedLength:
                case PortableDataType.RawDataVariableLength:
                case PortableDataType.RawDataLargeLength:
                    targetLength = targetUse.Length;
                    sourceLength = sourceUse.Length;
                    return((targetLength == 0 ? int.MaxValue : targetLength) >= (sourceLength == 0 ? int.MaxValue : sourceLength));
                }
                break;

            case PortableDataType.RawDataPicture:
            case PortableDataType.RawDataOleObject:
            case PortableDataType.TemporalTime:
            case PortableDataType.TemporalDate:
            case PortableDataType.OtherRowId:
            case PortableDataType.OtherObjectId:
                if (sourceType == targetType)
                {
                    return(true);
                }
                break;

            case PortableDataType.TemporalAutoTimestamp:
            case PortableDataType.TemporalDateAndTime:
                switch (sourceType)
                {
                case PortableDataType.TemporalAutoTimestamp:
                case PortableDataType.TemporalTime:
                case PortableDataType.TemporalDate:
                case PortableDataType.TemporalDateAndTime:
                    return(true);
                }
                break;

            case PortableDataType.LogicalTrueOrFalse:
            case PortableDataType.LogicalYesOrNo:
                switch (sourceType)
                {
                case PortableDataType.LogicalTrueOrFalse:
                case PortableDataType.LogicalYesOrNo:
                    return(true);
                }
                break;
            }
            return(false);
        }