private void BuildNestedFields(FieldInfo source, FieldInfo target, IEnumerable<FieldInfo> fields)
    {
      var buffer = fields.ToList();

      foreach (var field in buffer) {
        var clone = field.Clone();
        if (target.SkipVersion)
          clone.SkipVersion = true;
        clone.IsSystem = false;
        clone.IsLazyLoad = field.IsLazyLoad || target.IsLazyLoad;
        if (target.IsDeclared) {
          clone.Name = context.NameBuilder.BuildNestedFieldName(target, field);
          clone.OriginalName = field.OriginalName;
          // One-field reference
          if (target.IsEntity && buffer.Count == 1) {
            clone.MappingName = target.MappingName;
            clone.DefaultValue = target.DefaultValue;
          }
          else
            clone.MappingName = context.NameBuilder.BuildMappingName(target, field);
        }
        if (target.Fields.Contains(clone.Name))
          continue;
        clone.Parent = target;
        target.ReflectedType.Fields.Add(clone);

        if (field.IsStructure || field.IsEntity) {
          BuildNestedFields(source, clone, field.Fields);
          foreach (FieldInfo clonedFields in clone.Fields)
            target.Fields.Add(clonedFields);
        }
        else {
          if (field.Column!=null)
            clone.Column = BuildInheritedColumn(clone, field.Column);
        }
        if (target.IsStructure && clone.IsEntity && !IsAuxiliaryType(clone.ReflectedType)) {
          var origin = context.Model.Associations
            .Find(context.Model.Types[field.ValueType], true)
            .FirstOrDefault(a => a.OwnerField.Equals(field));
          if (origin!=null && !clone.IsInherited) {
            AssociationBuilder.BuildAssociation(context, origin, clone);
            context.DiscardedAssociations.Add(origin);
          }
        }
        if (!clone.IsStructure && !clone.IsEntitySet && !target.ReflectedType.IsInterface && 0!=(clone.Attributes & FieldAttributes.Indexed)) {
          var typeDef = context.ModelDef.Types[target.DeclaringType.UnderlyingType];
          var attribute = new IndexAttribute(clone.Name);
          var index = context.ModelDefBuilder.DefineIndex(typeDef, attribute);
          if (typeDef.Indexes.Contains(index.Name))
            throw new DomainBuilderException(
              string.Format(Strings.ExIndexWithNameXIsAlreadyRegistered, index.Name));

          typeDef.Indexes.Add(index);
          BuildLog.Info(Strings.LogIndexX, index.Name);
        }
      }
    }
Exemple #2
0
        private void BuildAssociations()
        {
            using (BuildLog.InfoRegion(Strings.LogBuildingX, Strings.Associations)) {
                PreprocessAssociations();
                foreach (var pair in context.PairedAssociations)
                {
                    if (context.DiscardedAssociations.Contains(pair.First))
                    {
                        continue;
                    }
                    if (!context.Model.Associations.Contains(pair.First))
                    {
                        continue;
                    }
                    AssociationBuilder.BuildPairedAssociation(pair.First, pair.Second);
                }

                foreach (var ai in context.DiscardedAssociations)
                {
                    context.Model.Associations.Remove(ai);
                }
                context.DiscardedAssociations.Clear();

                foreach (var association in context.Model.Associations)
                {
                    TryAddForeignKeyIndex(association);
                    if (association.IsPaired)
                    {
                        continue;
                    }
                    if (!association.OnOwnerRemove.HasValue)
                    {
                        association.OnOwnerRemove = association.OwnerField.IsEntitySet ? OnRemoveAction.Clear : OnRemoveAction.None;
                    }
                    if (!association.OnTargetRemove.HasValue)
                    {
                        association.OnTargetRemove = OnRemoveAction.Deny;
                    }
                }

                BuildAuxiliaryTypes(context.Model.Associations);
            }
        }
Exemple #3
0
        private FieldInfo BuildDeclaredField(TypeInfo type, FieldDef fieldDef)
        {
            BuildLog.Info(Strings.LogBuildingDeclaredFieldXY, type.Name, fieldDef.Name);

            var fieldInfo = new FieldInfo(type, fieldDef.Attributes)
            {
                UnderlyingProperty = fieldDef.UnderlyingProperty,
                Name         = fieldDef.Name,
                OriginalName = fieldDef.Name,
                MappingName  = fieldDef.MappingName,
                ValueType    = fieldDef.ValueType,
                ItemType     = fieldDef.ItemType,
                Length       = fieldDef.Length,
                Scale        = fieldDef.Scale,
                Precision    = fieldDef.Precision,
                Validators   = fieldDef.Validators,
            };

            if (fieldInfo.IsStructure && DeclaresOnValidate(fieldInfo.ValueType))
            {
                fieldInfo.Validators.Add(new StructureFieldValidator());
            }

            if (fieldInfo.IsEntitySet && DeclaresOnValidate(fieldInfo.ValueType))
            {
                fieldInfo.Validators.Add(new EntitySetFieldValidator());
            }

            type.Fields.Add(fieldInfo);

            if (fieldInfo.IsEntitySet)
            {
                AssociationBuilder.BuildAssociation(context, fieldDef, fieldInfo);
                return(fieldInfo);
            }

            if (fieldInfo.IsEntity)
            {
                var fields = context.Model.Types[fieldInfo.ValueType].Fields.Where(f => f.IsPrimaryKey);
                // Adjusting default value if any
                if (fields.Count() == 1 && fieldDef.DefaultValue != null)
                {
                    fieldInfo.DefaultValue =
                        ValueTypeBuilder.AdjustValue(fieldInfo, fields.First().ValueType, fieldDef.DefaultValue);
                }

                BuildNestedFields(null, fieldInfo, fields);

                if (!IsAuxiliaryType(type))
                {
                    AssociationBuilder.BuildAssociation(context, fieldDef, fieldInfo);
                    if (type.IsStructure)
                    {
                        fieldInfo.Associations.ForEach(a => context.DiscardedAssociations.Add(a));
                    }
                }

                // Adjusting type discriminator field for references
                if (fieldDef.IsTypeDiscriminator)
                {
                    type.Hierarchy.TypeDiscriminatorMap.Field = fieldInfo.Fields.First();
                }
            }

            if (fieldInfo.IsStructure)
            {
                BuildNestedFields(null, fieldInfo, context.Model.Types[fieldInfo.ValueType].Fields);
                var structureFullTextIndex = context.ModelDef.FullTextIndexes.TryGetValue(fieldInfo.ValueType);
                if (structureFullTextIndex != null)
                {
                    var hierarchyTypeInfo = context.Model.Types[fieldInfo.DeclaringType.UnderlyingType];
                    var structureTypeInfo = context.Model.Types[fieldInfo.ValueType];
                    var currentIndex      = context.ModelDef.FullTextIndexes.TryGetValue(hierarchyTypeInfo.UnderlyingType);
                    if (currentIndex == null)
                    {
                        currentIndex = new FullTextIndexDef(context.ModelDef.Types.TryGetValue(type.UnderlyingType));
                        context.ModelDef.FullTextIndexes.Add(currentIndex);
                    }

                    currentIndex.Fields.AddRange(structureFullTextIndex.Fields
                                                 .Select(f => new {
                        fieldInfo.DeclaringType
                        .StructureFieldMapping[new Pair <FieldInfo>(fieldInfo, structureTypeInfo.Fields[f.Name])].Name,
                        f.IsAnalyzed,
                        f.Configuration,
                        f.TypeFieldName
                    })
                                                 .Select(g => new FullTextFieldDef(g.Name, g.IsAnalyzed)
                    {
                        Configuration = g.Configuration, TypeFieldName = g.TypeFieldName
                    }));
                }
            }

            if (fieldInfo.IsPrimitive)
            {
                fieldInfo.DefaultValue         = fieldDef.DefaultValue;
                fieldInfo.DefaultSqlExpression = fieldDef.DefaultSqlExpression;
                fieldInfo.Column = BuildDeclaredColumn(fieldInfo);
                if (fieldDef.IsTypeDiscriminator)
                {
                    type.Hierarchy.TypeDiscriminatorMap.Field = fieldInfo;
                }
            }

            return(fieldInfo);
        }
Exemple #4
0
        private void PreprocessAssociations()
        {
            foreach (var typeInfo in context.Model.Types.Where(t => t.IsEntity && !t.IsAuxiliary))
            {
                // pair integrity escalation and consistency check
                typesWithProcessedInheritedAssociations.Add(typeInfo);
                var refFields = typeInfo.Fields.Where(f => f.IsEntity || f.IsEntitySet).ToList();
                // check for interface fields
                foreach (var refField in refFields)
                {
                    var parentIsPaired        = false;
                    var interfaceIsPaired     = false;
                    var interfaceAssociations = new List <AssociationInfo>();
                    var inheritedAssociations = new List <AssociationInfo>();
                    if (refField.IsDeclared && refField.IsInterfaceImplementation)
                    {
                        var implementedInterfaceFields = typeInfo.FieldMap
                                                         .GetImplementedInterfaceFields(refField);

                        foreach (var interfaceField in implementedInterfaceFields)
                        {
                            var field = interfaceField;
                            interfaceAssociations.AddRange(field.Associations);
                            interfaceIsPaired |= context.PairedAssociations.Any(pa => field.Associations.Contains(pa.First));
                        }
                    }
                    if (refField.IsInherited)
                    {
                        var ancestor = typeInfo.GetAncestor();
                        var field    = ancestor.Fields[refField.Name];
                        inheritedAssociations.AddRange(field.Associations);
                        parentIsPaired |= context.PairedAssociations.Any(pa => field.Associations.Contains(pa.First));
                    }

                    if (!parentIsPaired && !interfaceIsPaired)
                    {
                        List <Pair <AssociationInfo, string> > pairedToReverse;
                        if (pairedAssociationsToReverse.TryGetValue(typeInfo, out pairedToReverse))
                        {
                            foreach (var pair in pairedToReverse)
                            {
                                AssociationBuilder.BuildReversedAssociation(context, pair.First, pair.Second);
                            }
                        }
                        var field = refField;
                        var pairedAssociations = context.PairedAssociations
                                                 .Where(pa => field.Associations.Contains(pa.First))
                                                 .ToList();
                        if (pairedAssociations.Count > 0)
                        {
                            foreach (var paired in pairedAssociations)
                            {
                                paired.First.Ancestors.AddRange(interfaceAssociations);
                                if (paired.First.TargetType.IsInterface || typesWithProcessedInheritedAssociations.Contains(paired.First.TargetType))
                                {
                                    AssociationBuilder.BuildReversedAssociation(context, paired.First, paired.Second);
                                }
                                else
                                {
                                    List <Pair <AssociationInfo, string> > pairs;
                                    if (!pairedAssociationsToReverse.TryGetValue(paired.First.TargetType, out pairs))
                                    {
                                        pairs = new List <Pair <AssociationInfo, string> >();
                                        pairedAssociationsToReverse.Add(paired.First.TargetType, pairs);
                                    }
                                    pairs.Add(paired);
                                }
                            }
                            continue;
                        }
                    }

                    var fieldCopy = refField;
                    if (!parentIsPaired)
                    {
                        context.PairedAssociations.RemoveAll(pa => fieldCopy.Associations.Contains(pa.First));
                    }
                    Func <AssociationInfo, bool> associationFilter = a => context.PairedAssociations
                                                                     .Any(pa => a.TargetType.UnderlyingType.IsAssignableFrom(pa.First.OwnerType.UnderlyingType) &&
                                                                          pa.Second == a.OwnerField.Name &&
                                                                          a.OwnerType == pa.First.TargetType);
                    var associationsToKeep = refField.IsInterfaceImplementation
            ? refField.Associations
                                             .Where(associationFilter)
                                             .ToList()
            : refField.Associations.Count > 1
              ? refField.Associations
                                             .Where(associationFilter)
                                             .ToList()
              : refField.Associations.ToList();
                    var associationsToRemove = refField.Associations
                                               .Except(associationsToKeep)
                                               .ToList();

                    foreach (var association in associationsToRemove)
                    {
                        context.Model.Associations.Remove(association);
                        refField.Associations.Remove(association);
                    }
                    foreach (var association in associationsToKeep)
                    {
                        var interfaceAssociationsToRemove = interfaceAssociations
                                                            .Where(ia => ia.OwnerType != association.OwnerType)
                                                            .ToList();
                        association.Ancestors.AddRange(interfaceAssociationsToRemove);
                        foreach (var interfaceAssociation in interfaceAssociationsToRemove)
                        {
                            interfaceAssociations.Remove(interfaceAssociation);
                        }
                    }
                    refField.Associations.AddRange(interfaceAssociations);
                    foreach (var association in inheritedAssociations)
                    {
                        if (!refField.Associations.Contains(association.Name))
                        {
                            refField.Associations.Add(association);
                        }
                        if (!context.Model.Associations.Contains(association))
                        {
                            context.Model.Associations.Add(association);
                        }
                    }
                }
            }
        }