private static void AddAttributeAnnotation(EdmProperty property, Attribute a)
 {
     if (property != null)
     {
         var clrAttributes = property.Annotations.GetClrAttributes();
         if (clrAttributes != null)
         {
             if (!clrAttributes.Contains(a))
             {
                 clrAttributes.Add(a);
             }
         }
         else
         {
             property.Annotations.SetClrAttributes(
                 new List<Attribute>
                     {
                         a
                     });
         }
     }
 }
        private Tuple <FunctionParameter, bool> GetParameter(EdmProperty column, bool originalValue = false)
        {
            DebugCheck.NotNull(column);

            var columnMappings
                = (from esm in _entityContainerMapping.EntitySetMappings
                   from etm in esm.EntityTypeMappings
                   from mf in etm.MappingFragments
                   from cm in mf.FlattenedProperties
                   where cm.ColumnProperty.EdmEquals(column) &&
                   cm.ColumnProperty.DeclaringType.EdmEquals(column.DeclaringType)
                   select cm)
                  .ToList();

            var parameterBindings
                = _currentFunctionMapping
                  .ParameterBindings
                  .Where(
                      pb => columnMappings
                      .Any(cm => pb.MemberPath.Members.Reverse().SequenceEqual(cm.PropertyPath)))
                  .ToList();

            if (!parameterBindings.Any())
            {
                var iaColumnMappings
                    = (from asm in _entityContainerMapping.AssociationSetMappings
                       from tm in asm.TypeMappings
                       from mf in tm.MappingFragments
                       from epm in mf.PropertyMappings.OfType <EndPropertyMapping>()
                       from pm in epm.PropertyMappings
                       where pm.Column.EdmEquals(column) &&
                       pm.Column.DeclaringType.EdmEquals(column.DeclaringType)
                       select new EdmMember[]
                {
                    pm.Property,
                    epm.AssociationEnd
                })
                      .ToList();

                parameterBindings
                    = _currentFunctionMapping
                      .ParameterBindings
                      .Where(
                          pb => iaColumnMappings
                          .Any(epm => pb.MemberPath.Members.SequenceEqual(epm)))
                      .ToList();
            }

            if ((parameterBindings.Count == 0) &&
                column.IsPrimaryKeyColumn)
            {
                // Store generated key: Introduce a fake parameter which can
                // be replaced by a local variable in the sproc body.

                return
                    (Tuple.Create(
                         new FunctionParameter(
                             _storeGeneratedKeys[_nextStoreGeneratedKey++].Name,
                             column.TypeUsage,
                             ParameterMode.In), true));
            }

            if (parameterBindings.Count == 1)
            {
                return(Tuple.Create(parameterBindings[0].Parameter, parameterBindings[0].IsCurrent));
            }

            if (parameterBindings.Count == 0)
            {
                return(null);
            }

            Debug.Assert(parameterBindings.Count == 2);

            var parameterBinding
                = originalValue
                    ? parameterBindings.Single(pb => !pb.IsCurrent)
                    : parameterBindings.Single(pb => pb.IsCurrent);

            return(Tuple.Create(parameterBinding.Parameter, parameterBinding.IsCurrent));
        }
Beispiel #3
0
        internal void Configure(
            DbDatabaseMapping databaseMapping,
            MappingFragment fragment,
            EntityType entityType,
            DbProviderManifest providerManifest)
        {
            DebugCheck.NotNull(fragment);
            DebugCheck.NotNull(providerManifest);

            var discriminatorColumn
                = fragment.Table.Properties
                  .SingleOrDefault(c => string.Equals(c.Name, Discriminator, StringComparison.Ordinal));

            if (discriminatorColumn == null)
            {
                var typeUsage
                    = providerManifest.GetStoreType(DatabaseMappingGenerator.DiscriminatorTypeUsage);

                discriminatorColumn
                    = new EdmProperty(Discriminator, typeUsage)
                    {
                    Nullable = false
                    };

                TablePrimitiveOperations.AddColumn(fragment.Table, discriminatorColumn);
            }

            if (AnyBaseTypeToTableWithoutColumnCondition(
                    databaseMapping, entityType, fragment.Table, discriminatorColumn))
            {
                discriminatorColumn.Nullable = true;
            }

            var existingConfiguration
                = discriminatorColumn.GetConfiguration() as Properties.Primitive.PrimitivePropertyConfiguration;

            if (Value != null)
            {
                ConfigureColumnType(providerManifest, existingConfiguration, discriminatorColumn);

                fragment.AddDiscriminatorCondition(discriminatorColumn, Value);
            }
            else
            {
                if (string.IsNullOrWhiteSpace(discriminatorColumn.TypeName))
                {
                    var typeUsage
                        = providerManifest.GetStoreType(DatabaseMappingGenerator.DiscriminatorTypeUsage);

                    discriminatorColumn.PrimitiveType = (PrimitiveType)typeUsage.EdmType;
                    discriminatorColumn.MaxLength     = DatabaseMappingGenerator.DiscriminatorMaxLength;
                    discriminatorColumn.Nullable      = false;
                }

                GetOrCreateConfiguration <Properties.Primitive.PrimitivePropertyConfiguration>().IsNullable = true;

                fragment.AddNullabilityCondition(discriminatorColumn, true);
            }

            if (_configuration == null)
            {
                return;
            }

            if (existingConfiguration != null)
            {
                string errorMessage;
                if ((existingConfiguration.OverridableConfigurationParts &
                     OverridableConfigurationParts.OverridableInCSpace) !=
                    OverridableConfigurationParts.OverridableInCSpace &&
                    !existingConfiguration.IsCompatible(
                        _configuration, inCSpace: true, errorMessage: out errorMessage))
                {
                    throw Error.ConflictingColumnConfiguration(discriminatorColumn, fragment.Table, errorMessage);
                }
            }

            if (_configuration.IsNullable != null)
            {
                discriminatorColumn.Nullable = _configuration.IsNullable.Value;
            }

            _configuration.Configure(discriminatorColumn, fragment.Table, providerManifest);
        }
Beispiel #4
0
 private static StorageMappingFragment GetFragmentForPropertyMapping(
     StorageEntityTypeMapping entityTypeMapping, EdmProperty property)
 {
     return(entityTypeMapping.MappingFragments
            .SingleOrDefault(tmf => tmf.ColumnMappings.Any(pm => pm.PropertyPath.Last() == property)));
 }
Beispiel #5
0
        /// <summary>
        /// Converts the DbExpression equivalent of:
        ///
        /// SELECT CASE
        ///     WHEN a._from0 THEN SUBTYPE1()
        ///     ...
        ///     WHEN a._from[n-2] THEN SUBTYPE_n-1()
        ///     ELSE SUBTYPE_n
        /// FROM
        ///     SELECT
        ///         b.C1..., b.Cn
        ///         CASE WHEN b.Discriminator = SUBTYPE1_Value THEN true ELSE false AS _from0
        ///         ...
        ///         CASE WHEN b.Discriminator = SUBTYPE_n_Value THEN true ELSE false AS _from[n-1]
        ///     FROM TSet AS b
        ///     WHERE b.Discriminator = SUBTYPE1_Value... OR x.Discriminator = SUBTYPE_n_Value
        /// AS a
        /// WHERE a._from0... OR a._from[n-1]
        ///
        /// into the DbExpression equivalent of the following, which is matched as a TPH discriminator
        /// by the <see cref="System.Data.Mapping.ViewGeneration.GeneratedView"/> class and so allows a <see cref="System.Data.Mapping.ViewGeneration.DiscriminatorMap"/>
        /// to be produced for the view, which would not otherwise be possible. Note that C1 through Cn
        /// are only allowed to be scalars or complex type constructors based on direct property references
        /// to the store entity set's scalar properties.
        ///
        /// SELECT CASE
        ///     WHEN y.Discriminator = SUBTTYPE1_Value THEN SUBTYPE1()
        ///     ...
        ///     WHEN y.Discriminator = SUBTYPE_n-1_Value THEN SUBTYPE_n-1()
        ///     ELSE SUBTYPE_n()
        /// FROM
        ///     SELECT x.C1..., x.Cn, Discriminator FROM TSet AS x
        ///     WHERE x.Discriminator = SUBTYPE1_Value... OR x.Discriminator = SUBTYPE_n_Value
        /// AS y
        ///
        /// </summary>
        private static DbExpression SimplifyNestedTphDiscriminator(DbExpression expression)
        {
            DbProjectExpression entityProjection    = (DbProjectExpression)expression;
            DbFilterExpression  booleanColumnFilter = (DbFilterExpression)entityProjection.Input.Expression;
            DbProjectExpression rowProjection       = (DbProjectExpression)booleanColumnFilter.Input.Expression;
            DbFilterExpression  discriminatorFilter = (DbFilterExpression)rowProjection.Input.Expression;

            List <DbExpression>         predicates         = FlattenOr(booleanColumnFilter.Predicate).ToList();
            List <DbPropertyExpression> propertyPredicates =
                predicates.OfType <DbPropertyExpression>()
                .Where(px => px.Instance.ExpressionKind == DbExpressionKind.VariableReference &&
                       ((DbVariableReferenceExpression)px.Instance).VariableName == booleanColumnFilter.Input.VariableName).ToList();

            if (predicates.Count != propertyPredicates.Count)
            {
                return(null);
            }

            List <string> predicateColumnNames = propertyPredicates.Select(px => px.Property.Name).ToList();

            Dictionary <object, DbComparisonExpression> discriminatorPredicates = new Dictionary <object, DbComparisonExpression>();

            if (!TypeSemantics.IsEntityType(discriminatorFilter.Input.VariableType) ||
                !TryMatchDiscriminatorPredicate(discriminatorFilter, (compEx, discValue) => discriminatorPredicates.Add(discValue, compEx)))
            {
                return(null);
            }

            EdmProperty             discriminatorProp = (EdmProperty)((DbPropertyExpression)((DbComparisonExpression)discriminatorPredicates.First().Value).Left).Property;
            DbNewInstanceExpression rowConstructor    = (DbNewInstanceExpression)rowProjection.Projection;
            RowType resultRow = TypeHelpers.GetEdmType <RowType>(rowConstructor.ResultType);
            Dictionary <string, DbComparisonExpression> inputPredicateMap    = new Dictionary <string, DbComparisonExpression>();
            Dictionary <string, DbComparisonExpression> selectorPredicateMap = new Dictionary <string, DbComparisonExpression>();
            Dictionary <string, DbExpression>           columnValues         = new Dictionary <string, DbExpression>(rowConstructor.Arguments.Count);

            for (int idx = 0; idx < rowConstructor.Arguments.Count; idx++)
            {
                string       propName  = resultRow.Properties[idx].Name;
                DbExpression columnVal = rowConstructor.Arguments[idx];
                if (predicateColumnNames.Contains(propName))
                {
                    if (columnVal.ExpressionKind != DbExpressionKind.Case)
                    {
                        return(null);
                    }
                    DbCaseExpression casePredicate = (DbCaseExpression)columnVal;
                    if (casePredicate.When.Count != 1 ||
                        !TypeSemantics.IsBooleanType(casePredicate.Then[0].ResultType) || !TypeSemantics.IsBooleanType(casePredicate.Else.ResultType) ||
                        casePredicate.Then[0].ExpressionKind != DbExpressionKind.Constant || casePredicate.Else.ExpressionKind != DbExpressionKind.Constant ||
                        (bool)((DbConstantExpression)casePredicate.Then[0]).Value != true || (bool)((DbConstantExpression)casePredicate.Else).Value != false)
                    {
                        return(null);
                    }

                    DbPropertyExpression comparedProp;
                    object constValue;
                    if (!TryMatchPropertyEqualsValue(casePredicate.When[0], rowProjection.Input.VariableName, out comparedProp, out constValue) ||
                        comparedProp.Property != discriminatorProp ||
                        !discriminatorPredicates.ContainsKey(constValue))
                    {
                        return(null);
                    }

                    inputPredicateMap.Add(propName, discriminatorPredicates[constValue]);
                    selectorPredicateMap.Add(propName, (DbComparisonExpression)casePredicate.When[0]);
                }
                else
                {
                    columnValues.Add(propName, columnVal);
                }
            }

            // Build a new discriminator-based filter that only includes the same rows allowed by the higher '_from0' column-based filter
            DbExpression newDiscriminatorPredicate = Helpers.BuildBalancedTreeInPlace <DbExpression>(new List <DbExpression>(inputPredicateMap.Values), (left, right) => DbExpressionBuilder.Or(left, right));

            discriminatorFilter = discriminatorFilter.Input.Filter(newDiscriminatorPredicate);

            DbCaseExpression    entitySelector = (DbCaseExpression)entityProjection.Projection;
            List <DbExpression> newWhens       = new List <DbExpression>(entitySelector.When.Count);
            List <DbExpression> newThens       = new List <DbExpression>(entitySelector.Then.Count);

            for (int idx = 0; idx < entitySelector.When.Count; idx++)
            {
                DbPropertyExpression    propWhen   = (DbPropertyExpression)entitySelector.When[idx];
                DbNewInstanceExpression entityThen = (DbNewInstanceExpression)entitySelector.Then[idx];

                DbComparisonExpression discriminatorWhen;
                if (!selectorPredicateMap.TryGetValue(propWhen.Property.Name, out discriminatorWhen))
                {
                    return(null);
                }
                newWhens.Add(discriminatorWhen);

                DbExpression inputBoundEntityConstructor = ValueSubstituter.Substitute(entityThen, entityProjection.Input.VariableName, columnValues);
                newThens.Add(inputBoundEntityConstructor);
            }

            DbExpression     newElse           = ValueSubstituter.Substitute(entitySelector.Else, entityProjection.Input.VariableName, columnValues);
            DbCaseExpression newEntitySelector = DbExpressionBuilder.Case(newWhens, newThens, newElse);

            DbExpression result = discriminatorFilter.BindAs(rowProjection.Input.VariableName).Project(newEntitySelector);

            return(result);
        }
 protected virtual void VisitEdmProperty(EdmProperty item)
 {
     VisitEdmNamedMetadataItem(item);
     if (item.PropertyType != null)
     {
         VisitEdmTypeReference(item.PropertyType);
     }
 }
        private string GetFacetString(EdmProperty column)
        {
            StringBuilder sql = new StringBuilder();
              Facet facet;
              Facet fcDateTimePrecision = null;

              ReadOnlyMetadataCollection<Facet> facets = column.TypeUsage.Facets;

              if (column.TypeUsage.EdmType.BaseType.Name == "String")
              {
            // types tinytext, mediumtext, text & longtext don't have a length.
            if (!column.TypeUsage.EdmType.Name.EndsWith("text", StringComparison.OrdinalIgnoreCase))
            {
              if (facets.TryGetValue("MaxLength", true, out facet))
            sql.AppendFormat(" ({0})", facet.Value);
            }
              }
              else if (column.TypeUsage.EdmType.BaseType.Name == "Decimal")
              {
            Facet fcScale;
            Facet fcPrecision;
            if (facets.TryGetValue("Scale", true, out fcScale) && facets.TryGetValue("Precision", true, out fcPrecision))
            {
              // Enforce scale to a reasonable value.
              int scale = fcScale.Value == null ? 0 : ( int )( byte )fcScale.Value;
              if (scale == 0)
            scale = MySqlProviderManifest.DEFAULT_DECIMAL_SCALE;
              sql.AppendFormat("( {0}, {1} ) ", fcPrecision.Value, scale);
            }
              }
              else if (column.TypeUsage.EdmType.BaseType.Name == "DateTime")
              {
            if (serverVersion >= new Version(5, 6) && facets.TryGetValue("Precision", true, out fcDateTimePrecision))
            {
               if (Convert.ToByte(fcDateTimePrecision.Value) >= 1)
              sql.AppendFormat("( {0} ) ", fcDateTimePrecision.Value);
            }
              }

              if (facets.TryGetValue("Nullable", true, out facet) && (bool)facet.Value == false)
            sql.Append(" NOT NULL");

              if (facets.TryGetValue("StoreGeneratedPattern", true, out facet))
              {
            if (facet.Value.Equals(StoreGeneratedPattern.Identity))
            {

              if (column.TypeUsage.EdmType.BaseType.Name.StartsWith("Int"))
            sql.Append(" AUTO_INCREMENT UNIQUE");
              else if (column.TypeUsage.EdmType.BaseType.Name == "Guid")
            _guidIdentityColumns.Add(column.Name);
              else if (serverVersion >= new Version(5, 6) && column.TypeUsage.EdmType.BaseType.Name == "DateTime")
            sql.AppendFormat(" DEFAULT CURRENT_TIMESTAMP{0}", fcDateTimePrecision != null && Convert.ToByte(fcDateTimePrecision.Value) >= 1 ? "( " + fcDateTimePrecision.Value.ToString() + " )" : "");
              else
            throw new MySqlException("Invalid identity column type.");
            }
              }
              return sql.ToString();
        }
Beispiel #8
0
 protected virtual void VisitEdmProperty(EdmProperty item)
 {
     VisitMetadataItem(item);
 }
Beispiel #9
0
 protected virtual void Visit(EdmProperty edmProperty)
 {
     Visit(edmProperty.TypeUsage);
 }
Beispiel #10
0
        /// <summary>
        /// Gets the name of the column for the property from the metadata.
        /// Set nestedProperty for the property of a complex type to lookup.
        /// </summary>
        /// <param name="mappingFragment">EF metadata for finding mappings.</param>
        /// <param name="edmProperty">The of the model to find the column for (for simple types), or for complex types this is the containing complex type.</param>
        /// <param name="nestedProperty">Only required to map complex types. The property of the complex type to find the column name for.</param>
        /// <returns>The column name for the property</returns>
        /// <exception cref="EnumGeneratorException">
        /// </exception>
        private static string GetColumnName(StructuralTypeMapping mappingFragment, EdmProperty edmProperty, EdmProperty nestedProperty = null)
        {
            var propertyMapping = GetPropertyMapping(mappingFragment, edmProperty);

            if (nestedProperty != null)
            {
                var complexPropertyMapping = propertyMapping as ComplexPropertyMapping;
                if (complexPropertyMapping == null)
                {
                    throw new EnumGeneratorException(string.Format(
                                                         "Failed to cast complex property mapping for {0}.{1} to ComplexPropertyMapping", edmProperty, nestedProperty));
                }
                var complexTypeMappings = complexPropertyMapping.TypeMappings;
                if (complexTypeMappings.Count() != 1)
                {
                    throw new EnumGeneratorException(string.Format(
                                                         "{0} complexPropertyMapping TypeMappings found for property {1}.{2}", complexTypeMappings.Count(), edmProperty, nestedProperty));
                }
                var complexTypeMapping = complexTypeMappings.Single();
                var propertyMappings   = complexTypeMapping.PropertyMappings.Where(pm => pm.Property.Name == nestedProperty.Name).ToList();
                if (propertyMappings.Count() != 1)
                {
                    throw new EnumGeneratorException(string.Format(
                                                         "{0} complexMappings found for property {1}.{2}", propertyMappings.Count(), edmProperty, nestedProperty));
                }

                propertyMapping = propertyMappings.Single();
            }

            return(GetColumnNameFromPropertyMapping(edmProperty, propertyMapping));
        }
 /// <summary>
 /// Creates a ValueConditionMapping instance.
 /// </summary>
 /// <param name="propertyOrColumn">An EdmProperty that specifies a property or column.</param>
 /// <param name="value">An object that specifies the value to compare with.</param>
 public ValueConditionMapping(EdmProperty propertyOrColumn, object value)
     : base(Check.NotNull(propertyOrColumn, "propertyOrColumn"), Check.NotNull(value, "value"), null)
 {
 }
Beispiel #12
0
        private static PropertyMapping GetPropertyMapping(StructuralTypeMapping mappingFragment, EdmProperty edmProperty)
        {
            var matches = mappingFragment.PropertyMappings.Where(m => m.Property.Name == edmProperty.Name).ToList();

            if (matches.Count() != 1)
            {
                throw new EnumGeneratorException(string.Format(
                                                     "{0} matches found for property {1}", matches.Count(), edmProperty));
            }
            var match = matches.Single();

            return(match);
        }
Beispiel #13
0
            protected override void VisitEdmProperty(EdmProperty item)
            {
                Dispatch(item);

                base.VisitEdmProperty(item);
            }
        private static IList <FunctionParameter> GetStoreReturnParameters(
            this DbModel model, MethodInfo methodInfo, FunctionAttribute functionAttribute)
        {
            ParameterInfo returnParameterInfo = methodInfo.ReturnParameter;

            if (returnParameterInfo == null || returnParameterInfo.ParameterType == typeof(void))
            {
                throw new NotSupportedException($"The return type of {methodInfo.Name} is not supported.");
            }

            ParameterAttribute returnParameterAttribute = returnParameterInfo.GetCustomAttribute <ParameterAttribute>();

            ResultTypeAttribute[] returnTypeAttributes = methodInfo.GetCustomAttributes <ResultTypeAttribute>().ToArray();

            if (functionAttribute.Type == FunctionType.StoredProcedure)
            {
                if (returnParameterAttribute != null)
                {
                    throw new NotSupportedException(
                              $"{nameof(ParameterAttribute)} for return value of method {methodInfo.Name} is not supported.");
                }

                return(new FunctionParameter[0]);
            }

            if (returnTypeAttributes.Any())
            {
                throw new NotSupportedException($"{nameof(ResultTypeAttribute)} for method {methodInfo.Name} is not supported.");
            }

            if (functionAttribute.Type == FunctionType.TableValuedFunction)
            {
                if (returnParameterAttribute != null)
                {
                    throw new NotSupportedException(
                              $"{nameof(ParameterAttribute)} for return value of method {methodInfo.Name} is not supported.");
                }

                /*
                 * <CollectionType>
                 * <RowType>
                 * <Property Name="PersonID" Type="int" Nullable="false" />
                 * <Property Name="FirstName" Type="nvarchar" MaxLength="50" />
                 * <Property Name="LastName" Type="nvarchar" MaxLength="50" />
                 * <Property Name="JobTitle" Type="nvarchar" MaxLength="50" />
                 * <Property Name="BusinessEntityType" Type="nvarchar" MaxLength="50" />
                 * </RowType>
                 * </CollectionType>
                 */
                // returnParameterInfo.ParameterType is IQueryable<T>.
                Type           storeReturnParameterClrType        = returnParameterInfo.ParameterType.GetGenericArguments().Single();
                StructuralType modelReturnParameterStructuralType = model.GetModelStructualType(
                    storeReturnParameterClrType, methodInfo);
                ComplexType modelReturnParameterComplexType = modelReturnParameterStructuralType as ComplexType;
                RowType     storeReturnParameterRowType;
                if (modelReturnParameterComplexType != null)
                {
                    storeReturnParameterRowType = RowType.Create(
                        modelReturnParameterComplexType.Properties.Select(property =>
                                                                          EdmProperty.Create(property.Name, model.ProviderManifest.GetStoreType(property.TypeUsage))),
                        null);
                }
                else
                {
                    EntityType modelReturnParameterEntityType = modelReturnParameterStructuralType as EntityType;
                    if (modelReturnParameterEntityType != null)
                    {
                        storeReturnParameterRowType = RowType.Create(
                            modelReturnParameterEntityType.Properties.Select(property => property.Clone()),
                            null);
                    }
                    else
                    {
                        throw new NotSupportedException($"Structural type {modelReturnParameterStructuralType.FullName} of method {methodInfo.Name} cannot be converted to {nameof(RowType)}.");
                    }
                }

                return(new FunctionParameter[]
                {
                    FunctionParameter.Create(
                        "ReturnType",
                        storeReturnParameterRowType.GetCollectionType(),     // Collection of RowType.
                        ParameterMode.ReturnValue)
                });
            }

            if (functionAttribute.Type == FunctionType.NonComposableScalarValuedFunction)
            {
                // Non-composable scalar-valued function.
                return(new FunctionParameter[0]);
            }

            // Composable scalar-valued/Aggregate/Built in/Niladic function.
            // <Function Name="ufnGetProductListPrice" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="true" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo"
            //    ReturnType ="money">
            PrimitiveType storeReturnParameterPrimitiveType = model.GetStoreParameterPrimitiveType(methodInfo, returnParameterInfo, functionAttribute);

            return(new FunctionParameter[]
            {
                FunctionParameter.Create("ReturnType", storeReturnParameterPrimitiveType, ParameterMode.ReturnValue)
            });
        }
        internal void WritePropertyElementHeader(EdmProperty property)
        {
            _xmlWriter.WriteStartElement(CsdlConstants.Element_Property);
            _xmlWriter.WriteAttributeString(CsdlConstants.Attribute_Name, property.Name);
            _xmlWriter.WriteAttributeString(CsdlConstants.Attribute_Type, GetTypeReferenceName(property.PropertyType));

            if (property.CollectionKind
                != EdmCollectionKind.Default)
            {
                _xmlWriter.WriteAttributeString(
                    CsdlConstants.Attribute_CollectionKind, property.CollectionKind.ToString());
            }

            if (property.ConcurrencyMode
                == EdmConcurrencyMode.Fixed)
            {
                _xmlWriter.WriteAttributeString(CsdlConstants.Attribute_ConcurrencyMode, CsdlConstants.Value_Fixed);
            }

            if (property.Annotations.GetClrAttributes() != null)
            {
                var epmCount = 0;
                foreach (var a in property.Annotations.GetClrAttributes())
                {
                    if (a.GetType().FullName.Equals(DataServicesMimeTypeAttribute, StringComparison.Ordinal))
                    {
                        var mimeType = a.GetType().GetProperty("MimeType").GetValue(a, null) as string;
                        _xmlWriter.WriteAttributeString(DataServicesPrefix, "MimeType", DataServicesNamespace, mimeType);
                    }
                    else if (a.GetType().FullName.Equals(
                        DataServicesEntityPropertyMappingAttribute, StringComparison.Ordinal))
                    {
                        var suffix = epmCount == 0
                                         ? String.Empty
                                         : string.Format(CultureInfo.InvariantCulture, "_{0}", epmCount);

                        var sourcePath = a.GetType().GetProperty("SourcePath").GetValue(a, null) as string;
                        var slashIndex = sourcePath.IndexOf("/", StringComparison.Ordinal);
                        if (slashIndex != -1
                            && slashIndex + 1 < sourcePath.Length)
                        {
                            _xmlWriter.WriteAttributeString(
                                DataServicesPrefix, "FC_SourcePath" + suffix, DataServicesNamespace,
                                sourcePath.Substring(slashIndex + 1));
                        }

                        // There are three ways to write out this attribute
                        var syndicationItem = a.GetType().GetProperty("TargetSyndicationItem").GetValue(a, null);
                        var keepInContext = a.GetType().GetProperty("KeepInContent").GetValue(a, null).ToString();
                        var criteriaValueProperty = a.GetType().GetProperty("CriteriaValue");
                        string criteriaValue = null;
                        if (criteriaValueProperty != null)
                        {
                            criteriaValue = criteriaValueProperty.GetValue(a, null) as string;
                        }

                        if (criteriaValue != null)
                        {
                            _xmlWriter.WriteAttributeString(
                                DataServicesPrefix,
                                "FC_TargetPath" + suffix,
                                DataServicesNamespace,
                                SyndicationItemPropertyToString(syndicationItem));
                            _xmlWriter.WriteAttributeString(
                                DataServicesPrefix, "FC_KeepInContent" + suffix, DataServicesNamespace,
                                keepInContext);
                            _xmlWriter.WriteAttributeString(
                                DataServicesPrefix, "FC_CriteriaValue" + suffix, DataServicesNamespace,
                                criteriaValue);
                        }
                        else if (string.Equals(
                            syndicationItem.ToString(), "CustomProperty", StringComparison.Ordinal))
                        {
                            var targetPath = a.GetType().GetProperty("TargetPath").GetValue(a, null).ToString();
                            var targetNamespacePrefix =
                                a.GetType().GetProperty("TargetNamespacePrefix").GetValue(a, null).ToString();
                            var targetNamespaceUri =
                                a.GetType().GetProperty("TargetNamespaceUri").GetValue(a, null).ToString();

                            _xmlWriter.WriteAttributeString(
                                DataServicesPrefix, "FC_TargetPath" + suffix, DataServicesNamespace, targetPath);
                            _xmlWriter.WriteAttributeString(
                                DataServicesPrefix, "FC_NsUri" + suffix, DataServicesNamespace,
                                targetNamespaceUri);
                            _xmlWriter.WriteAttributeString(
                                DataServicesPrefix, "FC_NsPrefix" + suffix, DataServicesNamespace,
                                targetNamespacePrefix);
                            _xmlWriter.WriteAttributeString(
                                DataServicesPrefix, "FC_KeepInContent" + suffix, DataServicesNamespace,
                                keepInContext);
                        }
                        else
                        {
                            var contextKind = a.GetType().GetProperty("TargetTextContentKind").GetValue(a, null);

                            _xmlWriter.WriteAttributeString(
                                DataServicesPrefix,
                                "FC_TargetPath" + suffix,
                                DataServicesNamespace,
                                SyndicationItemPropertyToString(syndicationItem));
                            _xmlWriter.WriteAttributeString(
                                DataServicesPrefix,
                                "FC_ContentKind" + suffix,
                                DataServicesNamespace,
                                SyndicationTextContentKindToString(contextKind));
                            _xmlWriter.WriteAttributeString(
                                DataServicesPrefix, "FC_KeepInContent" + suffix, DataServicesNamespace,
                                keepInContext);
                        }

                        epmCount++;
                    }
                }
            }
            WritePropertyTypeFacets(property.PropertyType);

            DataModelAnnotation annotation;
            if (property.Annotations.TryGetByName(SsdlConstants.Attribute_StoreGeneratedPattern, out annotation))
            {
                _xmlWriter.WriteAttributeString(
                    SsdlConstants.Attribute_StoreGeneratedPattern, CsdlConstants.AnnotationNamespace,
                    annotation.Value.ToString());
            }
        }
Beispiel #16
0
 /// <summary>
 /// When overriden returns <c>true</c> if <paramref name="dependentProperty" /> should be part of the foreign key.
 /// </summary>
 /// <param name="associationType"> The association type being configured. </param>
 /// <param name="dependentAssociationEnd"> The dependent end. </param>
 /// <param name="dependentProperty"> The candidate property on the dependent end. </param>
 /// <param name="principalEntityType"> The principal end entity type. </param>
 /// <param name="principalKeyProperty"> A key property on the principal end that is a candidate target for the foreign key. </param>
 /// <returns>true if dependentProperty should be a part of the foreign key; otherwise, false.</returns>
 protected abstract bool MatchDependentKeyProperty(
     AssociationType associationType,
     AssociationEndMember dependentAssociationEnd,
     EdmProperty dependentProperty,
     EntityType principalEntityType,
     EdmProperty principalKeyProperty);
 protected override void VisitEdmProperty(EdmProperty item)
 {
     _schemaWriter.WritePropertyElementHeader(item);
     base.VisitEdmProperty(item);
     _schemaWriter.WriteEndElement();
 }
 /// <summary>
 /// Initialises a new instance of the <see cref="PropertyPath"/> class for the specified <see cref="EdmProperty"/> with no next path segment.
 /// </summary>
 /// <param name="property">The <see cref="EdmProperty"/> that the path segment represents.</param>
 private PropertyPath(EdmProperty property)
     : this(property, null)
 {
 }
Beispiel #19
0
 /// <summary>
 /// Determines whether given property is concurrency check property.
 /// </summary>
 /// <param name="edmProperty">The edm property.</param>
 /// <returns></returns>
 private static bool? IsConcurrencyProperty(EdmProperty edmProperty) {
     foreach (var facet in edmProperty.TypeUsage.Facets)
         if (facet.Name == "ConcurrencyMode" && facet.Value != null && facet.IsUnbounded == false)
             return facet.Value.ToString() == "Fixed";
     return null;
 }
 /// <summary>
 /// Initialises a new instance of the <see cref="PropertyPath"/> class for the specified <see cref="EdmProperty"/> with the next path segment.
 /// </summary>
 /// <param name="property">The <see cref="EdmProperty"/> that the path segment represents.</param>
 /// <param name="next">The next <see cref="PropertyPath"/> in the property path.</param>
 private PropertyPath(EdmProperty property, PropertyPath next)
 {
     Property = property;
     Next     = next;
 }
 /// <summary>
 /// Initialises a new instance of the <see cref="PropertyAccessNode"/> class.
 /// </summary>
 /// <param name="property">The property being referenced in the query.</param>
 internal PropertyAccessNode(EdmProperty property)
 {
     this.Property = property;
 }
 /// <summary>
 /// Creates the <see cref="PropertyPath"/> for the given <see cref="EdmProperty"/>.
 /// </summary>
 /// <param name="property">The <see cref="EdmProperty"/> that the path segment represents.</param>
 /// <returns>The <see cref="PropertyPath"/> for the given EdmProperty.</returns>
 internal static PropertyPath For(EdmProperty property)
 => s_edmPropertyCache.GetOrAdd(property ?? throw new ArgumentNullException(nameof(property)), p => new PropertyPath(p));
 /// <summary>
 ///     Constrcut a new member mapping metadata object
 /// </summary>
 /// <param name="edmProperty"> </param>
 /// <param name="clrProperty"> </param>
 internal ObjectComplexPropertyMapping(EdmProperty edmProperty, EdmProperty clrProperty)
     : base(edmProperty, clrProperty)
 {
 }
 public ColumnAssertions(EdmProperty column)
 {
     _column = column;
 }
Beispiel #25
0
        public void Can_create_non_composable_function_with_multiple_results()
        {
            DbProviderManifest providerManifest;
            var containerMapping = GetContainerMapping(out providerManifest);

            var cTypeUsageInt = TypeUsage.Create(
                PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32),
                new[]
            {
                Facet.Create(MetadataItem.NullableFacetDescription, false)
            });
            var sTypeUsageInt = TypeUsage.Create(
                providerManifest.GetStoreType(cTypeUsageInt).EdmType,
                new[]
            {
                Facet.Create(MetadataItem.NullableFacetDescription, false)
            });
            var cTypeUsageString = TypeUsage.CreateDefaultTypeUsage(
                PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String));
            var sTypeUsageString = providerManifest.GetStoreType(cTypeUsageString);

            var complexType = ComplexType.Create(
                "RT1", "N", DataSpace.CSpace,
                new[]
            {
                EdmProperty.Create("P1", cTypeUsageInt),
                EdmProperty.Create("P2", cTypeUsageString)
            },
                null);

            var entityType = EntityType.Create(
                "RT2", "N", DataSpace.CSpace,
                new[] { "P3" },
                new[]
            {
                EdmProperty.Create("P3", cTypeUsageInt),
                EdmProperty.Create("P4", cTypeUsageString),
            },
                null);

            var rowType1 = RowType.Create(
                new[]
            {
                EdmProperty.Create("C1", sTypeUsageInt),
                EdmProperty.Create("C2", sTypeUsageString)
            },
                null);

            var rowType2 = RowType.Create(
                new[]
            {
                EdmProperty.Create("C3", sTypeUsageInt),
                EdmProperty.Create("C4", sTypeUsageString)
            },
                null);

            var functionImport = EdmFunction.Create(
                "F", "N", DataSpace.CSpace,
                new EdmFunctionPayload
            {
                IsComposable     = false,
                ReturnParameters = new[]
                {
                    FunctionParameter.Create("R1", complexType.GetCollectionType(), ParameterMode.ReturnValue),
                    FunctionParameter.Create("R2", entityType.GetCollectionType(), ParameterMode.ReturnValue)
                },
                EntitySets = new[]
                {
                    new EntitySet(),
                    new EntitySet()
                }
            },
                null);

            var targetFunction = EdmFunction.Create(
                "SF", "N", DataSpace.SSpace,
                new EdmFunctionPayload
            {
                IsComposable     = false,
                ReturnParameters = new[]
                {
                    FunctionParameter.Create("R1", rowType1.GetCollectionType(), ParameterMode.ReturnValue),
                    FunctionParameter.Create("R2", rowType2.GetCollectionType(), ParameterMode.ReturnValue)
                },
                EntitySets = new []
                {
                    new EntitySet(),
                    new EntitySet()
                }
            },
                null);

            var resultMappings
                = new List <FunctionImportResultMapping>
                {
                new FunctionImportResultMapping(),
                new FunctionImportResultMapping()
                };

            resultMappings[0].AddTypeMapping(new FunctionImportComplexTypeMapping(
                                                 complexType,
                                                 new Collection <FunctionImportReturnTypePropertyMapping>()
            {
                new FunctionImportReturnTypeScalarPropertyMapping("P1", "C1"),
                new FunctionImportReturnTypeScalarPropertyMapping("P2", "C2"),
            }));

            resultMappings[1].AddTypeMapping(new FunctionImportEntityTypeMapping(
                                                 Enumerable.Empty <EntityType>(),
                                                 new [] { entityType },
                                                 new Collection <FunctionImportReturnTypePropertyMapping>()
            {
                new FunctionImportReturnTypeScalarPropertyMapping("P3", "C3"),
                new FunctionImportReturnTypeScalarPropertyMapping("P4", "C4")
            },
                                                 Enumerable.Empty <FunctionImportEntityTypeMappingCondition>()));

            var functionImportMapping = new FunctionImportMappingNonComposable(
                functionImport,
                targetFunction,
                resultMappings,
                containerMapping);

            Assert.Equal(resultMappings.Count, functionImportMapping.ResultMappings.Count);

            functionImportMapping.ResultMappings.Each(m => Assert.False(m.IsReadOnly));
            functionImportMapping.SetReadOnly();
            functionImportMapping.ResultMappings.Each(m => Assert.True(m.IsReadOnly));
        }
 public PropertyAssertions(EdmProperty property, IEnumerable <EdmProperty> columns)
 {
     _property = property;
     _columns  = columns;
 }
Beispiel #27
0
        private void AppendType(EdmProperty column)
        {
            var type = column.TypeUsage;

            // check for rowversion-like configurations
            Facet storeGenFacet;
            var   isTimestamp = false;

            if (type.EdmType.Name == "binary"
                &&
                8 == type.GetMaxLength()
                &&
                column.TypeUsage.Facets.TryGetValue("StoreGeneratedPattern", false, out storeGenFacet)
                &&
                storeGenFacet.Value != null
                &&
                StoreGeneratedPattern.Computed == (StoreGeneratedPattern)storeGenFacet.Value)
            {
                isTimestamp = true;
                AppendIdentifier("rowversion");
            }
            else
            {
                var typeName = type.EdmType.Name;
                // Special case: the EDM treats 'nvarchar(max)' as a type name, but SQL Server treats
                // it as a type 'nvarchar' and a type qualifier. As such, we can't escape the entire
                // type name as the EDM sees it.
                const string maxSuffix = "(max)";
                if (type.EdmType.BuiltInTypeKind == BuiltInTypeKind.PrimitiveType &&
                    typeName.EndsWith(maxSuffix, StringComparison.Ordinal))
                {
                    Debug.Assert(
                        new[] { "nvarchar(max)", "varchar(max)", "varbinary(max)" }.Contains(typeName),
                        "no other known SQL Server primitive types types accept (max)");
                    AppendIdentifier(typeName.Substring(0, typeName.Length - maxSuffix.Length));
                    AppendSql("(max)");
                }
                else
                {
                    AppendIdentifier(typeName);
                }
                switch (type.EdmType.Name)
                {
                case "decimal":
                case "numeric":
                    AppendSqlInvariantFormat("({0}, {1})", type.GetPrecision(), type.GetScale());
                    break;

                case "datetime2":
                case "datetimeoffset":
                case "time":
                    AppendSqlInvariantFormat("({0})", type.GetPrecision());
                    break;

                case "binary":
                case "varbinary":
                case "nvarchar":
                case "varchar":
                case "char":
                case "nchar":
                    AppendSqlInvariantFormat("({0})", type.GetMaxLength());
                    break;

                default:
                    break;
                }
            }
            AppendSql(column.Nullable ? " null" : " not null");

            if (!isTimestamp &&
                column.TypeUsage.Facets.TryGetValue("StoreGeneratedPattern", false, out storeGenFacet)
                &&
                storeGenFacet.Value != null)
            {
                var storeGenPattern = (StoreGeneratedPattern)storeGenFacet.Value;
                if (storeGenPattern == StoreGeneratedPattern.Identity)
                {
                    if (type.EdmType.Name == "uniqueidentifier")
                    {
                        AppendSql(" default newid()");
                    }
                    else
                    {
                        AppendSql(" identity");
                    }
                }
            }
        }
        internal virtual CollectionColumnMap CreateColumnMapFromReaderAndClrType(
            DbDataReader reader, Type type, MetadataWorkspace workspace)
        {
            DebugCheck.NotNull(reader);
            DebugCheck.NotNull(type);
            DebugCheck.NotNull(workspace);

            // we require a default constructor
            var constructor = type.GetDeclaredConstructor();

            if (type.IsAbstract() ||
                (null == constructor && !type.IsValueType()))
            {
                throw new InvalidOperationException(Strings.ObjectContext_InvalidTypeForStoreQuery(type));
            }

            // build a LINQ expression used by result assembly to create results
            var memberInfo = new List <Tuple <MemberAssignment, int, EdmProperty> >();

            foreach (var prop in type.GetInstanceProperties()
                     .Select(p => p.GetPropertyInfoForSet()))
            {
                // for enums unwrap the type if nullable
                var propertyUnderlyingType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
                var propType = propertyUnderlyingType.IsEnum() ? propertyUnderlyingType.GetEnumUnderlyingType() : prop.PropertyType;

                EdmType modelType;
                int     ordinal;

                if (TryGetColumnOrdinalFromReader(reader, prop.Name, out ordinal) &&
                    workspace.TryDetermineCSpaceModelType(propType, out modelType) &&
                    (Helper.IsScalarType(modelType)) &&
                    prop.CanWriteExtended() &&
                    prop.GetIndexParameters().Length == 0 &&
                    null != prop.Setter())
                {
                    memberInfo.Add(
                        Tuple.Create(
                            Expression.Bind(prop, Expression.Parameter(prop.PropertyType, "placeholder")),
                            ordinal,
                            new EdmProperty(prop.Name, TypeUsage.Create(modelType))));
                }
            }
            // initialize members in the order in which they appear in the reader
            var members         = new MemberInfo[memberInfo.Count];
            var memberBindings  = new MemberBinding[memberInfo.Count];
            var propertyMaps    = new ColumnMap[memberInfo.Count];
            var modelProperties = new EdmProperty[memberInfo.Count];
            var i = 0;

            foreach (var memberGroup in memberInfo.GroupBy(tuple => tuple.Item2).OrderBy(tuple => tuple.Key))
            {
                // make sure that a single column isn't contributing to multiple properties
                if (memberGroup.Count() != 1)
                {
                    throw new InvalidOperationException(
                              Strings.ObjectContext_TwoPropertiesMappedToSameColumn(
                                  reader.GetName(memberGroup.Key),
                                  String.Join(", ", memberGroup.Select(tuple => tuple.Item3.Name).ToArray())));
                }

                var member     = memberGroup.Single();
                var assignment = member.Item1;
                var ordinal    = member.Item2;
                var modelProp  = member.Item3;

                members[i]         = assignment.Member;
                memberBindings[i]  = assignment;
                propertyMaps[i]    = new ScalarColumnMap(modelProp.TypeUsage, modelProp.Name, 0, ordinal);
                modelProperties[i] = modelProp;
                i++;
            }
            var newExpr = null == constructor?Expression.New(type) : Expression.New(constructor);

            var init         = Expression.MemberInit(newExpr, memberBindings);
            var initMetadata = InitializerMetadata.CreateProjectionInitializer(
                (EdmItemCollection)workspace.GetItemCollection(DataSpace.CSpace), init);

            // column map (a collection of rows with InitializerMetadata markup)
            var rowType = new RowType(modelProperties, initMetadata);
            var rowMap  = new RecordColumnMap(
                TypeUsage.Create(rowType),
                "DefaultTypeProjection", propertyMaps, null);
            CollectionColumnMap collectionMap = new SimpleCollectionColumnMap(
                rowType.GetCollectionType().TypeUsage,
                rowType.Name, rowMap, null, null);

            return(collectionMap);
        }
 /// <summary>Creates an IsNullConditionMapping instance.</summary>
 /// <param name="propertyOrColumn">An EdmProperty that specifies a property or column.</param>
 /// <param name="isNull">A boolean that indicates whether to perform a null or a not-null check.</param>
 public IsNullConditionMapping(EdmProperty propertyOrColumn, bool isNull)
     : base(Check.NotNull <EdmProperty>(propertyOrColumn, nameof(propertyOrColumn)), (object)null, new bool?(isNull))
 {
 }
Beispiel #30
0
 private string GetIndexName(IndexAttribute index, EdmProperty property)
 {
     return(index.Name == null?IndexNameCreator.CreateName(entitySet.ElementType.GetTableName(), property.Name) : NameCreator.EscapeName(index.Name));
 }
 internal void WriteDelaredKeyPropertyRefElement(EdmProperty property)
 {
     _xmlWriter.WriteStartElement(CsdlConstants.Element_PropertyRef);
     _xmlWriter.WriteAttributeString(CsdlConstants.Attribute_Name, property.Name);
     _xmlWriter.WriteEndElement();
 }
Beispiel #32
0
 protected internal override void VisitEdmProperty(EdmProperty item)
 {
     _schemaWriter.WritePropertyElementHeader(item);
     base.VisitEdmProperty(item);
     _schemaWriter.WriteEndElement();
 }
 private void WriteScalarPropertyElement(EdmProperty property, DbTableColumnMetadata column)
 {
     _xmlWriter.WriteStartElement(MslConstants.Element_ScalarProperty);
     _xmlWriter.WriteAttributeString(MslConstants.Attribute_Name, property.Name);
     _xmlWriter.WriteAttributeString(MslConstants.Attribute_ColumnName, column.Name);
     _xmlWriter.WriteEndElement();
 }
Beispiel #34
0
        // <summary>
        // Validates the scalar property on the cspace side and ospace side and creates a new
        // ObjectPropertyMapping, if everything maps property
        // </summary>
        private static ObjectPropertyMapping LoadScalarPropertyMapping(EdmProperty edmProperty, EdmProperty objectProperty)
        {
            Debug.Assert(
                Helper.IsScalarType(edmProperty.TypeUsage.EdmType),
                "Only edm scalar properties expected");
            Debug.Assert(
                Helper.IsScalarType(objectProperty.TypeUsage.EdmType),
                "Only object scalar properties expected");

            return(new ObjectPropertyMapping(edmProperty, objectProperty));
        }
		static GenerateColumnResult GenerateColumn(EdmProperty property)
		{
			var column = new StringBuilder();
			var columnComments = new Dictionary<string, string>();
			column.Append(SqlGenerator.QuoteIdentifier(property.Name));
			column.Append(" ");
			column.Append(SqlGenerator.GetSqlPrimitiveType(property.TypeUsage));
			switch (MetadataHelpers.GetEdmType<PrimitiveType>(property.TypeUsage).PrimitiveTypeKind)
			{
				case PrimitiveTypeKind.Boolean:
					column.AppendFormat(" CHECK ({0} IN (1,0))", SqlGenerator.QuoteIdentifier(property.Name));
					columnComments.Add(property.Name, "#BOOL#");
					break;
				case PrimitiveTypeKind.Guid:
					columnComments.Add(property.Name, "#GUID#");
					break;
			}
			if (!property.Nullable)
			{
				column.Append(" NOT NULL");
			}
			return new GenerateColumnResult() { ColumnName = column.ToString(), ColumnComments = columnComments };
		}
 public PropertyMappingFake(EdmProperty property)
     : base(property)
 {
 }
Beispiel #37
0
 /// <summary>
 /// Gets the scale.
 /// </summary>
 /// <param name="edmProperty">The EDM property.</param>
 /// <returns></returns>
 private static int? GetScale(EdmProperty edmProperty) {
     foreach (var facet in edmProperty.TypeUsage.Facets)
         if (facet.Name == "Scale" && facet.Value != null && facet.IsUnbounded == false)
             return Convert.ToInt32(facet.Value);
     return null;
 }
        /// <summary>
        ///     Determines whether the given query view matches the discriminator map pattern.
        /// </summary>
        internal static bool TryCreateDiscriminatorMap(EntitySet entitySet, DbExpression queryView, out DiscriminatorMap discriminatorMap)
        {
            discriminatorMap = null;

            if (queryView.ExpressionKind
                != DbExpressionKind.Project)
            {
                return(false);
            }
            var project = (DbProjectExpression)queryView;

            if (project.Projection.ExpressionKind
                != DbExpressionKind.Case)
            {
                return(false);
            }
            var caseExpression = (DbCaseExpression)project.Projection;

            if (project.Projection.ResultType.EdmType.BuiltInTypeKind
                != BuiltInTypeKind.EntityType)
            {
                return(false);
            }

            // determine value domain by walking filter
            if (project.Input.Expression.ExpressionKind
                != DbExpressionKind.Filter)
            {
                return(false);
            }
            var filterExpression = (DbFilterExpression)project.Input.Expression;

            var discriminatorDomain = new HashSet <object>();

            if (
                !ViewSimplifier.TryMatchDiscriminatorPredicate(
                    filterExpression, (equalsExp, discriminatorValue) => discriminatorDomain.Add(discriminatorValue)))
            {
                return(false);
            }

            var typeMap                        = new List <KeyValuePair <object, EntityType> >();
            var propertyMap                    = new Dictionary <EdmProperty, DbExpression>();
            var relPropertyMap                 = new Dictionary <RelProperty, DbExpression>();
            var typeToRelPropertyMap           = new Dictionary <EntityType, List <RelProperty> >();
            DbPropertyExpression discriminator = null;

            EdmProperty discriminatorProperty = null;

            for (var i = 0; i < caseExpression.When.Count; i++)
            {
                var when = caseExpression.When[i];
                var then = caseExpression.Then[i];

                var projectionVariableName = project.Input.VariableName;

                DbPropertyExpression currentDiscriminator;
                object discriminatorValue;
                if (
                    !ViewSimplifier.TryMatchPropertyEqualsValue(
                        when, projectionVariableName, out currentDiscriminator, out discriminatorValue))
                {
                    return(false);
                }

                // must be the same discriminator in every case
                if (null == discriminatorProperty)
                {
                    discriminatorProperty = (EdmProperty)currentDiscriminator.Property;
                }
                else if (discriminatorProperty != currentDiscriminator.Property)
                {
                    return(false);
                }
                discriminator = currentDiscriminator;

                // right hand side must be entity type constructor
                EntityType currentType;
                if (!TryMatchEntityTypeConstructor(then, propertyMap, relPropertyMap, typeToRelPropertyMap, out currentType))
                {
                    return(false);
                }

                // remember type + discriminator value
                typeMap.Add(new KeyValuePair <object, EntityType>(discriminatorValue, currentType));

                // remove discriminator value from domain
                discriminatorDomain.Remove(discriminatorValue);
            }

            // make sure only one member of discriminator domain remains...
            if (1 != discriminatorDomain.Count)
            {
                return(false);
            }

            // check default case
            EntityType elseType;

            if (null == caseExpression.Else
                ||
                !TryMatchEntityTypeConstructor(caseExpression.Else, propertyMap, relPropertyMap, typeToRelPropertyMap, out elseType))
            {
                return(false);
            }
            typeMap.Add(new KeyValuePair <object, EntityType>(discriminatorDomain.Single(), elseType));

            // Account for cases where some type in the hierarchy specifies a rel-property, but another
            // type in the hierarchy does not
            if (!CheckForMissingRelProperties(relPropertyMap, typeToRelPropertyMap))
            {
                return(false);
            }

            // since the store may right-pad strings, ensure discriminator values are unique in their trimmed
            // form
            var discriminatorValues = typeMap.Select(map => map.Key);
            var uniqueValueCount    = discriminatorValues.Distinct(TrailingSpaceComparer.Instance).Count();
            var valueCount          = typeMap.Count;

            if (uniqueValueCount != valueCount)
            {
                return(false);
            }

            discriminatorMap = new DiscriminatorMap(discriminator, typeMap, propertyMap, relPropertyMap, entitySet);
            return(true);
        }
Beispiel #39
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="entityMap"></param>
        /// <param name="edmProperty"></param>
        /// <param name="i"></param>
        /// <param name="prefix"></param>
        private void MapProperty(EntityMap entityMap, EdmProperty edmProperty, ref int i, ref string prefix)
        {
            var identity = entityMap.EdmType.FullName;
            var entityMembers = TphData[identity].Properties;
            var columnName = edmProperty.Name;

            if (entityMembers.Length <= i)
            {
                return;
            }
            EdmMember edmMember = entityMembers[i];

            // check if is complex type
            if (string.IsNullOrEmpty(prefix) && edmMember.TypeUsage.EdmType.GetType() == typeof(ComplexType))
            {
                prefix = edmMember.Name;
                ++i;
            }

            string propName;

            if (prefix != null)
            {
                if (columnName.StartsWith(prefix + "_"))
                {
                    propName = columnName.Replace('_', '.');
                }
                else
                {
                    prefix = null;
                    propName = edmMember.Name;
                    ++i;
                }
            }
            else
            {
                propName = entityMembers[i++].Name;
            }

            var propInfo = entityMap.Type.GetProperty(propName, '.');
            if (propInfo == null)
            {
                // entity does not contain such property
                return;
            }

            PropertyMap propertyMap;
            try
            {
                /*
                var mi = SqlProviderServices.Instance.GetType().GetMethod("GetSqlDbType", BindingFlags.NonPublic | BindingFlags.Static);
                var parameterInfos = mi.GetParameters();

                var parameters = new List<object>();
                parameters.Add(edmProperty.TypeUsage);
                parameters.Add(false);
                parameters.Add(SqlVersion);
                parameters.Add(null);
                parameters.Add(null);
                parameters.Add(null);
                parameters.Add(null);

                SqlDbType sqlDbType = (SqlDbType) mi.Invoke(null, parameters.ToArray());
                */

                propertyMap = entityMap.MapProperty(propName, columnName);
                propertyMap.EdmProperty = edmProperty;
                propertyMap.EdmMember = edmMember;
                propertyMap.IsNavigationProperty = edmMember is NavigationProperty;
                propertyMap.IsFk = propertyMap.IsNavigationProperty || _fks.ContainsKey(edmMember);
                if (propertyMap.IsFk && _fks.ContainsKey(edmMember))
                {
                    propertyMap.FkTargetEdmMember = _fks[edmMember];
                    entityMap.AddFk(propertyMap);
                }
            }
            catch (Exception ex)
            {
                var errorMessage = string.Format("Failed to map propName {0} to column {1} on table {2} ({3})",
                    propName,
                    columnName,
                    entityMap.TableName,
                    entityMap.TypeFullName);

                throw new Exception(errorMessage, ex);
            }

            if (_pks[entityMap.TableName].Contains(columnName))
            {
                propertyMap.IsPk = true;
                entityMap.AddPk(propertyMap);
            }

            foreach (var facet in edmProperty.TypeUsage.Facets)
            {
                //System.Data.Entity.Core.Common.DbProviderManifest.ScaleFacetName
                switch (facet.Name)
                {
                    case "SRID":
                        try
                        {
                            propertyMap.SRID = (int?)facet.Value;
                        }
                        catch
                        {
                            // nothing to do
                        }
                        break;
                    case "IsStrict":
                        propertyMap.IsStrict = facet.Value != null && (bool)facet.Value;
                        break;
                    case "Unicode":
                        propertyMap.Unicode = facet.Value != null && (bool)facet.Value;
                        break;
                    case "FixedLength":
                        propertyMap.FixedLength = facet.Value != null && (bool)facet.Value;
                        break;
                    case "Precision":
                        propertyMap.Precision = (byte)facet.Value;
                        break;
                    case "Scale":
                        propertyMap.Scale = (byte)facet.Value;
                        break;
                    case "Nullable":
                        propertyMap.IsRequired = !(bool)facet.Value;
                        break;
                    case "DefaultValue":
                        propertyMap.DefaultValue = facet.Value;
                        break;
                    case "StoreGeneratedPattern":
                        propertyMap.IsIdentity = (StoreGeneratedPattern)facet.Value == StoreGeneratedPattern.Identity;
                        propertyMap.Computed = (StoreGeneratedPattern)facet.Value == StoreGeneratedPattern.Computed;
                        break;
                    case "MaxLength":
                        if (facet.Value == null)
                        {
                            propertyMap.MaxLength = int.MaxValue;
                        }
                        else
                        {
                            int result;
                            var val = facet.Value.ToString();
                            if (!Int32.TryParse(val, out result))
                            {
                                if (val == "Max")
                                {
                                    propertyMap.MaxLength = int.MaxValue;
                                }
                            }
                            propertyMap.MaxLength = result;
                        }
                        break;
                }
            }
        }
        public void AsPrimitive_should_create_property_type_and_facets()
        {
            var property = EdmProperty.CreatePrimitive("P", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String));

            Assert.NotNull(property.TypeUsage);
        }
        private static IEnumerable<IndexInfo> GetIndexes(EdmProperty prop)
        {
            var indexMetadata = prop.MetadataProperties
                .FirstOrDefault(x => x.Name == "http://schemas.microsoft.com/ado/2013/11/edm/customannotation:Index");

            if (indexMetadata == null)
            {
                yield break;
            }

            // Use dynamic in order to not force the need of EF6.1
            dynamic indexAnnotation = indexMetadata.Value;

            foreach (dynamic index in indexAnnotation.Indexes)
            {
                yield return GetIndexInfo(index);
            }
        }
        public void Can_generate_function_mappings_for_entity_type()
        {
            var functionMappingGenerator
                = new ModificationFunctionMappingGenerator(ProviderRegistry.Sql2008_ProviderManifest);

            var databaseMapping
                = new DbDatabaseMapping()
                  .Initialize(new EdmModel(DataSpace.CSpace), new EdmModel(DataSpace.SSpace));

            var entityType = new EntityType("E", "N", DataSpace.CSpace);

            var intProperty = EdmProperty.CreatePrimitive("Id", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.Int32));

            entityType.AddKeyMember(intProperty);

            var stringProperty = EdmProperty.CreatePrimitive("Name", PrimitiveType.GetEdmPrimitiveType(PrimitiveTypeKind.String));

            entityType.AddMember(stringProperty);

            var entitySetMapping
                = databaseMapping.AddEntitySetMapping(
                      databaseMapping.Model.AddEntitySet("ES", entityType));

            var storageEntityTypeMapping
                = new EntityTypeMapping(
                      new EntitySetMapping(new EntitySet(), databaseMapping.EntityContainerMappings.Single()));

            storageEntityTypeMapping.AddType(entityType);

            var storageMappingFragment = new MappingFragment(new EntitySet(), storageEntityTypeMapping, false);

            storageMappingFragment.AddColumnMapping(
                new ColumnMappingBuilder(new EdmProperty("C0", TypeUsage.Create(new PrimitiveType()
            {
                DataSpace = DataSpace.SSpace
            })), new[] { intProperty }));

            storageMappingFragment.AddColumnMapping(
                new ColumnMappingBuilder(new EdmProperty("C1", TypeUsage.Create(new PrimitiveType()
            {
                DataSpace = DataSpace.SSpace
            })), new[] { stringProperty }));

            storageEntityTypeMapping.AddFragment(storageMappingFragment);

            entitySetMapping.AddTypeMapping(storageEntityTypeMapping);

            functionMappingGenerator.Generate(entityType, databaseMapping);

            var modificationFunctionMapping
                = entitySetMapping.ModificationFunctionMappings.Single();

            Assert.NotNull(modificationFunctionMapping);

            var functionMapping = modificationFunctionMapping.InsertFunctionMapping;

            Assert.NotNull(functionMapping);
            Assert.Equal(2, functionMapping.ParameterBindings.Count);
            Assert.Null(functionMapping.ResultBindings);

            var function = functionMapping.Function;

            Assert.NotNull(function);
            Assert.Equal("E_Insert", function.Name);
            Assert.Equal(2, function.Parameters.Count);

            functionMapping = modificationFunctionMapping.UpdateFunctionMapping;

            Assert.NotNull(functionMapping);
            Assert.Equal(2, functionMapping.ParameterBindings.Count);
            Assert.Null(functionMapping.ResultBindings);

            function = functionMapping.Function;

            Assert.NotNull(function);
            Assert.Equal("E_Update", function.Name);
            Assert.Equal(2, function.Parameters.Count);

            functionMapping = modificationFunctionMapping.DeleteFunctionMapping;

            Assert.NotNull(functionMapping);
            Assert.Equal(1, functionMapping.ParameterBindings.Count);
            Assert.Null(functionMapping.ResultBindings);

            function = modificationFunctionMapping.DeleteFunctionMapping.Function;

            Assert.NotNull(function);
            Assert.Equal("E_Delete", function.Name);
            Assert.Equal(1, function.Parameters.Count);
        }