private static bool ValidateFacetValueInRange(
            PrimitiveType storePrimitiveType, string facetName, int actualValue, TableDetailsRow row, ICollection<EdmSchemaError> errors)
        {
            Debug.Assert(storePrimitiveType != null, "storePrimitiveType != null");
            Debug.Assert(facetName != null, "facetName != null");
            Debug.Assert(row != null, "row != null");
            Debug.Assert(errors != null, "errors != null");

            var facetDescription = storePrimitiveType.FacetDescriptions.SingleOrDefault(f => f.FacetName == facetName);

            if (facetDescription != null
                && !facetDescription.IsConstant)
            {
                if (actualValue < facetDescription.MinValue
                    || actualValue > facetDescription.MaxValue)
                {
                    errors.Add(
                        new EdmSchemaError(
                            string.Format(
                                CultureInfo.InvariantCulture,
                                Resources_VersioningFacade.ColumnFacetValueOutOfRange,
                                facetName,
                                actualValue,
                                facetDescription.MinValue,
                                facetDescription.MaxValue,
                                row.ColumnName,
                                row.GetMostQualifiedTableName()),
                            (int)ModelBuilderErrorCode.FacetValueOutOfRange,
                            EdmSchemaErrorSeverity.Warning));

                    return false;
                }
            }

            return true;
        }
        private bool ValidatePropertyType(TableDetailsRow row, ICollection<EdmSchemaError> errors)
        {
            string errorMessage = null;

            if (row.IsDataTypeNull())
            {
                errorMessage =
                    string.Format(
                        CultureInfo.InvariantCulture,
                        Resources_VersioningFacade.UnsupportedDataTypeUnknownType,
                        row.ColumnName,
                        row.GetMostQualifiedTableName());
            }
            else
            {
                bool excludedForVersion;
                var propertyType = GetStorePrimitiveTypeForVersion(row.DataType, out excludedForVersion);

                if (propertyType == null)
                {
                    errorMessage =
                        string.Format(
                            CultureInfo.InvariantCulture,
                            excludedForVersion
                                ? Resources_VersioningFacade.UnsupportedDataTypeForTarget
                                : Resources_VersioningFacade.UnsupportedDataType,
                            row.DataType,
                            row.GetMostQualifiedTableName(),
                            row.ColumnName);
                }
            }

            if (errorMessage != null)
            {
                errors.Add(
                    new EdmSchemaError(
                        errorMessage,
                        (int)ModelBuilderErrorCode.UnsupportedType,
                        EdmSchemaErrorSeverity.Warning));
            }

            return errorMessage == null;
        }
        private static EdmProperty ConfigurePropertyWithMaxLength(
            EdmProperty property, TableDetailsRow row, ICollection<EdmSchemaError> errors)
        {
            Debug.Assert(property != null, "property != null");
            Debug.Assert(
                property.PrimitiveType.PrimitiveTypeKind == PrimitiveTypeKind.String ||
                property.PrimitiveType.PrimitiveTypeKind == PrimitiveTypeKind.Binary,
                "string or binary property expected");
            Debug.Assert(row != null, "row != null");
            Debug.Assert(errors != null, "errors != null");

            if (!row.IsMaximumLengthNull())
            {
                if (
                    !ValidateFacetValueInRange(
                        property.PrimitiveType, DbProviderManifest.MaxLengthFacetName, row.MaximumLength, row, errors))
                {
                    return null;
                }

                // it is OK to set even if facet is const - it will be ignored
                property.MaxLength = row.MaximumLength;
            }

            return property;
        }
        private static EdmProperty ConfigureDateTimeLikeProperty(
            EdmProperty property, TableDetailsRow row, ICollection<EdmSchemaError> errors)
        {
            Debug.Assert(property != null, "property != null");
            Debug.Assert(
                property.PrimitiveType.PrimitiveTypeKind == PrimitiveTypeKind.Time ||
                property.PrimitiveType.PrimitiveTypeKind == PrimitiveTypeKind.DateTime ||
                property.PrimitiveType.PrimitiveTypeKind == PrimitiveTypeKind.DateTimeOffset,
                "datetime like property expected");
            Debug.Assert(row != null, "row != null");
            Debug.Assert(errors != null, "errors != null");

            if (!row.IsDateTimePrecisionNull())
            {
                if (
                    !ValidateFacetValueInRange(
                        property.PrimitiveType, DbProviderManifest.PrecisionFacetName, row.DateTimePrecision, row, errors))
                {
                    return null;
                }

                // it is OK to set even if facet is const - it will be ignored
                property.Precision = (byte)row.DateTimePrecision;
            }

            return property;
        }
        private static EdmProperty ConfigureProperty(EdmProperty property, TableDetailsRow row, IList<EdmSchemaError> errors)
        {
            Debug.Assert(property != null, "property != null");
            Debug.Assert(row != null, "row != null");
            Debug.Assert(errors != null, "errors != null");

            switch (property.PrimitiveType.PrimitiveTypeKind)
            {
                case PrimitiveTypeKind.Decimal:
                    property = ConfigureDecimalProperty(property, row, errors);
                    break;

                case PrimitiveTypeKind.DateTime:
                case PrimitiveTypeKind.DateTimeOffset:
                case PrimitiveTypeKind.Time:
                    property = ConfigureDateTimeLikeProperty(property, row, errors);
                    break;

                case PrimitiveTypeKind.String:
                case PrimitiveTypeKind.Binary:
                    property = ConfigurePropertyWithMaxLength(property, row, errors);
                    break;
            }

            if (property != null)
            {
                property.Nullable = row.IsNullable;

                if (!row.IsIsIdentityNull()
                    && row.IsIdentity)
                {
                    property.StoreGeneratedPattern = StoreGeneratedPattern.Identity;
                }
                else if (!row.IsIsServerGeneratedNull()
                         && row.IsServerGenerated)
                {
                    property.StoreGeneratedPattern = StoreGeneratedPattern.Computed;
                }
            }

            return property;
        }
        // internal to allow unit testing
        internal EdmProperty CreateProperty(TableDetailsRow row, IList<EdmSchemaError> errors)
        {
            Debug.Assert(row != null, "row != null");
            Debug.Assert(errors != null, "errors != null");

            if (!ValidatePropertyType(row, errors))
            {
                return null;
            }

            return ConfigureProperty(
                EdmProperty.CreatePrimitive(row.ColumnName, _nameToEdmType[row.DataType]),
                row,
                errors);
        }
            private static EdmModel BuildStoreModel(
                TableDetailsRow[] tableDetails,
                RelationshipDetailsRow[] relationshipDetails)
            {
                var storeSchemaDetails = new StoreSchemaDetails(
                    tableDetails,
                    new TableDetailsRow[0],
                    relationshipDetails,
                    new FunctionDetailsRowView[0],
                    new TableDetailsRow[0]);

                var storeModelBuilder = StoreModelBuilderTests.CreateStoreModelBuilder();

                return storeModelBuilder.Build(storeSchemaDetails);
            }