Beispiel #1
0
        private void NormalizeRelationAccessors(RelationDefinitionBase relation,
                                                string searchedName, EntityDefinition rdbEntity)
        {
            if (string.IsNullOrEmpty(searchedName))
            {
                return;
            }

            var q1 =
                from r in Model.GetActiveRelations().OfType <SelfRelationDefinition>()
                where r != relation && r.Entity.Identifier == rdbEntity.Identifier &&
                (r.Left.AccessorName == searchedName || r.Right.AccessorName == searchedName)
                select r as RelationDefinitionBase;

            var q2 =
                from r in Model.GetActiveRelations().OfType <RelationDefinition>()
                where r != relation &&
                (r.Right.Entity.Identifier == rdbEntity.Identifier &&
                 r.Left.AccessorName == searchedName) ||
                (r.Left.Entity.Identifier == rdbEntity.Identifier &&
                 r.Right.AccessorName == searchedName)
                select r as RelationDefinitionBase;

            int i = 0;

            foreach (RelationDefinitionBase r in q1.Union(q2))
            {
                i++;
                RelationDefinition     rd  = r as RelationDefinition;
                SelfRelationDefinition srd = r as SelfRelationDefinition;

                if (srd != null)
                {
                    if (srd.Left.AccessorName == searchedName)
                    {
                        srd.Left.AccessorName += i.ToString();
                    }
                    else if (srd.Right.AccessorName == searchedName)
                    {
                        srd.Right.AccessorName += i.ToString();
                    }
                }
                else if (rd != null)
                {
                    if (rd.Left.AccessorName == searchedName)
                    {
                        rd.Left.AccessorName += i.ToString();
                    }
                    else if (rd.Right.AccessorName == searchedName)
                    {
                        rd.Right.AccessorName += i.ToString();
                    }
                }
            }
        }
Beispiel #2
0
 private static void GenerateRelScript(SelfRelationTarget rt, StringBuilder script, bool unicodeStrings, RelationDefinitionBase rel)
 {
     for (int i = 0; i < rt.FieldName.Length; i++)
     {
         script.Append(rt.FieldName[i]).Append(" ");
         if (rel is SelfRelationDefinition)
         {
             SelfRelationDefinition   r  = rel as SelfRelationDefinition;
             ScalarPropertyDefinition sp = r.Properties.Skip(i).First();
             script.Append(GetType(sp.SourceField, sp.PropertyType, sp.Attributes, unicodeStrings)).Append(" NOT NULL");
         }
         else if (rel is RelationDefinition)
         {
             LinkTarget lt = rt as LinkTarget;
             ScalarPropertyDefinition sp = lt.Properties.Skip(i).First();
             script.Append(GetType(sp.SourceField, sp.PropertyType, sp.Attributes, unicodeStrings)).Append(" NOT NULL");
         }
         else
         {
             throw new NotSupportedException(rel.GetType().ToString());
         }
     }
 }
Beispiel #3
0
        protected void ProcessMany2Many()
        {
            foreach (SourceFragmentDefinition sf in SourceView.GetSourceFragments()
                     .Where(item => SourceView.GetSourceFields(item).All(clm => clm.IsFK) &&
                            item.Constraints.Count(citem => citem.ConstraintType == SourceConstraint.ForeignKeyConstraintTypeName) == 2))
            {
                List <LinkTarget> targets = new List <LinkTarget>();
                foreach (SourceConstraint fk in sf.Constraints.Where(item =>
                                                                     item.ConstraintType == SourceConstraint.ForeignKeyConstraintTypeName))
                {
                    var rels = SourceView.GetFKRelations(fk);
                    SourceFragmentDefinition m = rels.First().PKField.SourceFragment;

                    EntityDefinition e  = Model.GetEntity(GetEntityIdentifier(m.Selector, m.Name));
                    LinkTarget       lt = new LinkTarget(
                        e,
                        rels.Select(item => item.FKField.SourceFieldExpression).ToArray(),
                        rels.Select(item => e.GetPkProperties().Single(p => p.SourceFieldExpression == item.PKField.SourceFieldExpression).PropertyAlias).ToArray(),
                        rels.First().DeleteAction == SourceConstraint.CascadeAction
                        );
                    targets.Add(lt);
                }

                if (targets.Count != 2)
                {
                    continue;
                }

                if (targets[0].Entity.Name == targets[1].Entity.Name)
                {
                    LinkTarget             t      = targets[0];
                    SelfRelationDefinition newRel = new SelfRelationDefinition(
                        t.Entity, t.EntityProperties, targets[0], targets[1],
                        GetSourceFragment(sf), null);

                    if (sf.Constraints.Any(item => item.ConstraintType == SourceConstraint.PrimaryKeyConstraintTypeName))
                    {
                        newRel.Constraint = RelationConstraint.PrimaryKey;
                    }
                    else if (sf.Constraints.Any(item => item.ConstraintType == SourceConstraint.UniqueConstraintTypeName))
                    {
                        newRel.Constraint = RelationConstraint.Unique;
                    }

                    if (Model.GetSimilarRelation(newRel) == null)
                    {
                        string postFix = string.Empty;
                        if (string.IsNullOrEmpty(newRel.Left.AccessorName))
                        {
                            if (newRel.Left.FieldName.Length == 1)
                            {
                                if (newRel.Left.FieldName[0].EndsWith("_id", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    newRel.Left.AccessorName = newRel.Left.FieldName[0]
                                                               .Substring(0, newRel.Left.FieldName[0].Length - 3);
                                }
                                else if (newRel.Left.FieldName[0].EndsWith("id", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    newRel.Left.AccessorName = newRel.Left.FieldName[0]
                                                               .Substring(0, newRel.Left.FieldName[0].Length - 2);
                                }
                            }

                            if (string.IsNullOrEmpty(newRel.Left.AccessorName))
                            {
                                newRel.Left.AccessorName = newRel.Entity.Name;
                                postFix = "1";
                            }
                        }

                        if (string.IsNullOrEmpty(newRel.Right.AccessorName))
                        {
                            if (newRel.Left.FieldName.Length == 1)
                            {
                                if (newRel.Right.FieldName[0].EndsWith("_id", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    newRel.Right.AccessorName = newRel.Right.FieldName[0]
                                                                .Substring(0, newRel.Right.FieldName[0].Length - 3);
                                }
                                else if (newRel.Right.FieldName[0].EndsWith("id", StringComparison.InvariantCultureIgnoreCase))
                                {
                                    newRel.Right.AccessorName = newRel.Right.FieldName[0]
                                                                .Substring(0, newRel.Right.FieldName[0].Length - 2);
                                }
                            }

                            if (string.IsNullOrEmpty(newRel.Right.AccessorName))
                            {
                                newRel.Right.AccessorName = newRel.Entity.Name + postFix;
                            }
                        }
                        Model.AddRelation(newRel);
                    }
                }
                else
                {
                    RelationDefinition newRel = new RelationDefinition(
                        targets[0], targets[1], GetSourceFragment(sf), null);

                    if (sf.Constraints.Any(item => item.ConstraintType == SourceConstraint.PrimaryKeyConstraintTypeName))
                    {
                        newRel.Constraint = RelationConstraint.PrimaryKey;
                    }
                    else if (sf.Constraints.Any(item => item.ConstraintType == SourceConstraint.UniqueConstraintTypeName))
                    {
                        newRel.Constraint = RelationConstraint.Unique;
                    }

                    if (!Model.GetRelations().OfType <RelationDefinition>().Any(m => m.Equals(newRel)))
                    {
                        if (Model.HasSimilarRelationM2M(newRel))
                        {
                            if (string.IsNullOrEmpty(newRel.Left.AccessorName) ||
                                string.IsNullOrEmpty(newRel.Right.AccessorName))
                            {
                                var lst = from r in Model.GetRelations().OfType <RelationDefinition>()
                                          where
                                          !ReferenceEquals(r.Left, newRel.Left) &&
                                          !ReferenceEquals(r.Right, newRel.Right) &&
                                          (
                                    ((r.Left.Entity == newRel.Left.Entity &&
                                      string.IsNullOrEmpty(r.Right.AccessorName))
                                     &&
                                     (r.Right.Entity == newRel.Right.Entity &&
                                      string.IsNullOrEmpty(r.Left.AccessorName))) ||
                                    ((r.Left.Entity == newRel.Right.Entity &&
                                      string.IsNullOrEmpty(r.Right.AccessorName))
                                     &&
                                     (r.Right.Entity == newRel.Left.Entity &&
                                      string.IsNullOrEmpty(r.Left.AccessorName)))
                                          )
                                          select r;

                                if (lst.Count() > 0)
                                {
                                    foreach (RelationDefinition r in lst)
                                    {
                                        if (string.IsNullOrEmpty(r.Left.AccessorName))
                                        {
                                            r.Left.AccessorName = r.SourceFragment.Name.TrimEnd(']').TrimStart('[') +
                                                                  r.Right.Entity.Name;
                                        }
                                        if (string.IsNullOrEmpty(r.Right.AccessorName))
                                        {
                                            r.Right.AccessorName = r.SourceFragment.Name.TrimEnd(']').TrimStart('[') +
                                                                   r.Left.Entity.Name;
                                        }
                                    }

                                    if (string.IsNullOrEmpty(newRel.Left.AccessorName))
                                    {
                                        newRel.Left.AccessorName =
                                            newRel.SourceFragment.Name.TrimEnd(']').TrimStart('[') +
                                            newRel.Right.Entity.Name;
                                    }
                                    if (string.IsNullOrEmpty(newRel.Right.AccessorName))
                                    {
                                        newRel.Right.AccessorName =
                                            newRel.SourceFragment.Name.TrimEnd(']').TrimStart('[') +
                                            newRel.Left.Entity.Name;
                                    }
                                }
                            }
                        }
                        Model.AddRelation(newRel);
                    }
                }
            }

            foreach (SelfRelationDefinition rdb in Model.GetActiveRelations().OfType <SelfRelationDefinition>())
            {
                NormalizeRelationAccessors(rdb, rdb.Right.AccessorName, rdb.Entity);
                NormalizeRelationAccessors(rdb, rdb.Left.AccessorName, rdb.Entity);
            }

            foreach (RelationDefinition rdb in Model.GetActiveRelations().OfType <RelationDefinition>())
            {
                NormalizeRelationAccessors(rdb, rdb.Right.AccessorName, rdb.Right.Entity);
                NormalizeRelationAccessors(rdb, rdb.Left.AccessorName, rdb.Left.Entity);
            }
        }
        protected virtual void OnPopulateSchema()
        {
            Members.Add(SchemaDef);

            #region энам табличек

            CreateTablesLinkEnum(_entity, SchemaDef);

            #endregion энам табличек

            //#region bool ChangeValueType(EntityPropertyAttribute c, object value, ref object newvalue)

            //CreateChangeValueTypeMethod(_entity, SchemaDef);

            //#endregion bool ChangeValueType(EntityPropertyAttribute c, object value, ref object newvalue)

            //#region string[] GetSuppressedColumns()

            //// первоначальная реализация или есть отличие в suppressed properties
            //if (_entity.BaseEntity == null ||
            //    (_entity.BaseEntity.SuppressedProperties.Count + _entity.SuppressedProperties.Count != 0) ||
            //    _entity.BaseEntity.SuppressedProperties.Count != _entity.SuppressedProperties.Count ||
            //    !(_entity.SuppressedProperties.TrueForAll(p => _entity.BaseEntity.SuppressedProperties.Exists(pp => pp == p)) &&
            //    _entity.BaseEntity.SuppressedProperties.TrueForAll(p => _entity.SuppressedProperties.Exists(pp => pp == p))))
            //{

            //    var method = new CodeMemberMethod
            //    {
            //        Name = "GetSuppressedFields",
            //        // тип возвращаемого значения
            //        ReturnType = new CodeTypeReference(typeof(string[])),
            //        // модификаторы доступа
            //        Attributes = MemberAttributes.Public
            //    };

            //    SchemaDef.Members.Add(method);
            //    if (_entity.BaseEntity != null)
            //        method.Attributes |= MemberAttributes.Override;
            //    else
            //        // реализует метод базового класса
            //        method.ImplementationTypes.Add(typeof(IEntitySchemaBase));
            //    CodeArrayCreateExpression arrayExpression = new CodeArrayCreateExpression(
            //        new CodeTypeReference(typeof(string[]))
            //    );


            //    foreach (var suppressedProperty in _entity.SuppressedProperties)
            //    {
            //        arrayExpression.Initializers.Add(
            //            new CodePrimitiveExpression(suppressedProperty)
            //        );
            //    }

            //    method.Statements.Add(new CodeMethodReturnStatement(arrayExpression));
            //}

            //#endregion EntityPropertyAttribute[] GetSuppressedColumns()

            #region сущность реализует связь

            RelationDefinitionBase relation = _entity.Model.GetActiveRelations()
                                              .SingleOrDefault(item => item.UnderlyingEntity == _entity);

            if (relation != null)
            {
                SelfRelationDefinition sd = relation as SelfRelationDefinition;
                if (sd == null)
                {
                    ImplementIRelation((RelationDefinition)relation, _entity, SchemaDef);
                }
                else
                {
                    ImplementIRelation(sd, _entity, SchemaDef);
                }
            }

            #endregion сущность реализует связь

            //#region public void GetSchema(OrmSchemaBase schema, Type t)

            //if (_entity.BaseEntity == null)
            //{
            //    CodeMemberField schemaField = new CodeMemberField(
            //        new CodeTypeReference(typeof(Worm.ObjectMappingEngine)),
            //        "_schema"
            //        );
            //    CodeMemberField typeField = new CodeMemberField(
            //        new CodeTypeReference(typeof(Type)),
            //        "_entityType"
            //        );
            //    schemaField.Attributes = MemberAttributes.Family;
            //    SchemaDef.Members.Add(schemaField);
            //    typeField.Attributes = MemberAttributes.Family;
            //    SchemaDef.Members.Add(typeField);
            //    var method = new CodeMemberMethod
            //    {
            //        Name = "GetSchema",
            //        // тип возвращаемого значения
            //        ReturnType = null,
            //        // модификаторы доступа
            //        Attributes = MemberAttributes.Public | MemberAttributes.Final
            //    };

            //    SchemaDef.Members.Add(method);

            //    method.Parameters.Add(
            //        new CodeParameterDeclarationExpression(
            //            new CodeTypeReference(typeof(Worm.ObjectMappingEngine)),
            //            "schema"
            //            )
            //        );
            //    method.Parameters.Add(
            //        new CodeParameterDeclarationExpression(
            //            new CodeTypeReference(typeof(Type)),
            //            "t"
            //            )
            //        );
            //    // реализует метод базового класса
            //    method.ImplementationTypes.Add(typeof(ISchemaInit));
            //    method.Statements.Add(
            //        new CodeAssignStatement(
            //            new CodeFieldReferenceExpression(
            //                new CodeThisReferenceExpression(),
            //                "_schema"
            //                ),
            //            new CodeArgumentReferenceExpression("schema")
            //            )
            //        );
            //    method.Statements.Add(
            //        new CodeAssignStatement(
            //            new CodeFieldReferenceExpression(
            //                new CodeThisReferenceExpression(),
            //                "_entityType"
            //                ),
            //            new CodeArgumentReferenceExpression("t")
            //            )
            //        );
            //}

            //#endregion public void GetSchema(OrmSchemaBase schema, Type t)
        }
        private void ImplementIRelation(SelfRelationDefinition relation, EntityDefinition entity, CodeTypeDeclaration entitySchemaDefClass)
        {
            entitySchemaDefClass.BaseTypes.Add(new CodeTypeReference(typeof(IRelation)));

            #region Pair<string, Type> GetFirstType()
            CodeMemberMethod method = new CodeMemberMethod
            {
                Name = "GetFirstType",
                // тип возвращаемого значения
                ReturnType = new CodeTypeReference(typeof(IRelation.RelationDesc)),
                // модификаторы доступа
                Attributes = MemberAttributes.Public
            };
            // реализует метод базового класса
            method.ImplementationTypes.Add(typeof(IRelation));
            method.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodeObjectCreateExpression(
                        new CodeTypeReference(typeof(IRelation.RelationDesc)),
                        WXMLCodeDomGeneratorHelper.GetFieldNameReferenceExpression(Settings,
                                                                                   entity.GetActiveProperties().OfType <EntityPropertyDefinition>().SingleOrDefault(item =>
                                                                                                                                                                    item.SourceFields.Any(sf => relation.Direct.FieldName.Contains(sf.SourceFieldExpression)))
                                                                                   , false),
                        new CodeMethodInvokeExpression(
                            new CodeMethodReferenceExpression(
                                new CodeFieldReferenceExpression(
                                    new CodeThisReferenceExpression(),
                                    "_schema"
                                    ),
                                "GetTypeByEntityName"
                                ),
                            new CodePrimitiveExpression(relation.Entity.Name)
                            ),
                        new CodePrimitiveExpression(true)
                        )
                    )
                );
            entitySchemaDefClass.Members.Add(method);
            #endregion Pair<string, Type> GetFirstType()

            #region Pair<string, Type> GetSecondType()
            method = new CodeMemberMethod
            {
                Name = "GetSecondType",
                // тип возвращаемого значения
                ReturnType = new CodeTypeReference(typeof(IRelation.RelationDesc)),
                // модификаторы доступа
                Attributes = MemberAttributes.Public
            };
            // реализует метод базового класса
            method.ImplementationTypes.Add(typeof(IRelation));
            method.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodeObjectCreateExpression(
                        new CodeTypeReference(typeof(IRelation.RelationDesc)),
                        WXMLCodeDomGeneratorHelper.GetFieldNameReferenceExpression(Settings,
                                                                                   entity.GetActiveProperties().OfType <EntityPropertyDefinition>().SingleOrDefault(item =>
                                                                                                                                                                    item.SourceFields.Any(sf => relation.Reverse.FieldName.Contains(sf.SourceFieldExpression)))
                                                                                   , false),
                        new CodeMethodInvokeExpression(
                            new CodeMethodReferenceExpression(
                                new CodeFieldReferenceExpression(
                                    new CodeThisReferenceExpression(),
                                    "_schema"
                                    ),
                                "GetTypeByEntityName"
                                ),
                            new CodePrimitiveExpression(relation.Entity.Name)
                            ),
                        new CodePrimitiveExpression(false)
                        )
                    )
                );
            entitySchemaDefClass.Members.Add(method);
            #endregion Pair<string, Type> GetSecondType()
        }
        private void FillRelations()
        {
            if (_model.OwnRelations.Count() == 0)
            {
                return;
            }
            XmlNode relationsNode = CreateElement("EntityRelations");

            _ormXmlDocumentMain.DocumentElement.AppendChild(relationsNode);
            foreach (RelationDefinitionBase rel in _model.OwnRelations)
            {
                XmlElement relationElement;
                if (rel is RelationDefinition)
                {
                    RelationDefinition relation = (RelationDefinition)rel;

                    relationElement = CreateElement("Relation");

                    relationElement.SetAttribute("table", relation.SourceFragment.Identifier);
                    if (relation.Disabled)
                    {
                        relationElement.SetAttribute("disabled", XmlConvert.ToString(relation.Disabled));
                    }

                    XmlElement leftElement = CreateElement("Left");
                    leftElement.SetAttribute("entity", relation.Left.Entity.Identifier);
                    leftElement.SetAttribute("entityProperties", string.Join(" ", relation.Left.EntityProperties));
                    leftElement.SetAttribute("fieldName", string.Join(" ", relation.Left.FieldName));
                    leftElement.SetAttribute("cascadeDelete", XmlConvert.ToString(relation.Left.CascadeDelete));

                    if (!string.IsNullOrEmpty(relation.Left.AccessorName))
                    {
                        leftElement.SetAttribute("accessorName", relation.Left.AccessorName);
                    }

                    if (!string.IsNullOrEmpty(relation.Left.AccessorDescription))
                    {
                        leftElement.SetAttribute("accessorDescription", relation.Left.AccessorDescription);
                    }

                    if (relation.Left.AccessedEntityType != null)
                    {
                        leftElement.SetAttribute("accessedEntityType", relation.Left.AccessedEntityType.Identifier);
                    }

                    XmlElement rightElement = CreateElement("Right");
                    rightElement.SetAttribute("entity", relation.Right.Entity.Identifier);
                    rightElement.SetAttribute("entityProperties", string.Join(" ", relation.Right.EntityProperties));
                    rightElement.SetAttribute("fieldName", string.Join(" ", relation.Right.FieldName));
                    rightElement.SetAttribute("cascadeDelete", XmlConvert.ToString(relation.Right.CascadeDelete));

                    if (!string.IsNullOrEmpty(relation.Right.AccessorName))
                    {
                        rightElement.SetAttribute("accessorName", relation.Right.AccessorName);
                    }

                    if (!string.IsNullOrEmpty(relation.Right.AccessorDescription))
                    {
                        rightElement.SetAttribute("accessorDescription", relation.Right.AccessorDescription);
                    }

                    if (relation.Right.AccessedEntityType != null)
                    {
                        rightElement.SetAttribute("accessedEntityType", relation.Right.AccessedEntityType.Identifier);
                    }

                    if (relation.UnderlyingEntity != null)
                    {
                        relationElement.SetAttribute("underlyingEntity", relation.UnderlyingEntity.Identifier);
                    }

                    if (relation.Constraint != RelationConstraint.None)
                    {
                        relationElement.SetAttribute("constraint", relation.Constraint.ToString().ToLower());
                    }

                    relationElement.AppendChild(leftElement);
                    relationElement.AppendChild(rightElement);
                    relationsNode.AppendChild(relationElement);
                }
                else
                {
                    SelfRelationDefinition relation = (SelfRelationDefinition)rel;

                    relationElement = CreateElement("SelfRelation");

                    relationElement.SetAttribute("table", relation.SourceFragment.Identifier);
                    relationElement.SetAttribute("entity", relation.Entity.Identifier);
                    relationElement.SetAttribute("entityProperties", string.Join(" ", relation.EntityProperties));
                    if (relation.Disabled)
                    {
                        relationElement.SetAttribute("disabled", XmlConvert.ToString(relation.Disabled));
                    }

                    XmlElement directElement = CreateElement("Direct");

                    directElement.SetAttribute("fieldName", string.Join(" ", relation.Direct.FieldName));
                    directElement.SetAttribute("cascadeDelete", XmlConvert.ToString(relation.Direct.CascadeDelete));

                    if (!string.IsNullOrEmpty(relation.Direct.AccessorName))
                    {
                        directElement.SetAttribute("accessorName", relation.Direct.AccessorName);
                    }

                    if (!string.IsNullOrEmpty(relation.Direct.AccessorDescription))
                    {
                        directElement.SetAttribute("accessorDescription", relation.Direct.AccessorDescription);
                    }

                    if (relation.Direct.AccessedEntityType != null)
                    {
                        directElement.SetAttribute("accessedEntityType", relation.Direct.AccessedEntityType.Identifier);
                    }

                    XmlElement reverseElement = CreateElement("Reverse");
                    reverseElement.SetAttribute("fieldName", string.Join(" ", relation.Reverse.FieldName));
                    reverseElement.SetAttribute("cascadeDelete", XmlConvert.ToString(relation.Reverse.CascadeDelete));

                    if (!string.IsNullOrEmpty(relation.Reverse.AccessorName))
                    {
                        reverseElement.SetAttribute("accessorName", relation.Reverse.AccessorName);
                    }

                    if (!string.IsNullOrEmpty(relation.Reverse.AccessorDescription))
                    {
                        reverseElement.SetAttribute("accessorDescription", relation.Reverse.AccessorDescription);
                    }

                    if (relation.Reverse.AccessedEntityType != null)
                    {
                        reverseElement.SetAttribute("accessedEntityType", relation.Reverse.AccessedEntityType.Identifier);
                    }

                    if (relation.UnderlyingEntity != null)
                    {
                        relationElement.SetAttribute("underlyingEntity", relation.UnderlyingEntity.Identifier);
                    }

                    if (relation.Constraint != RelationConstraint.None)
                    {
                        relationElement.SetAttribute("constraint", relation.Constraint.ToString().ToLower());
                    }

                    relationElement.AppendChild(directElement);
                    relationElement.AppendChild(reverseElement);
                }
                if (rel.Constants.Count > 0)
                {
                    var constantsElement = CreateElement("Constants");
                    relationElement.InsertBefore(constantsElement, relationElement.FirstChild);

                    foreach (var constantDescriptor in rel.Constants)
                    {
                        var constantElement = CreateElement("Constant");
                        constantsElement.AppendChild(constantElement);

                        constantElement.SetAttribute("name", constantDescriptor.Name);
                        constantElement.SetAttribute("value", constantDescriptor.Value);
                    }
                }

                if (rel.Action != MergeAction.Merge)
                {
                    relationElement.SetAttribute("action", rel.Action.ToString());
                }

                relationsNode.AppendChild(relationElement);
            }
        }
        private void CreateForeignKeys(StringBuilder script, ISourceProvider provider)
        {
            var fks = Model.GetActiveEntities().SelectMany(item => item.GetProperties()
                                                           .OfType <EntityPropertyDefinition>()
                                                           ).Where(item => item.SourceFragment != null);

            List <string> names = new List <string>();

            bool hdr = false;

            foreach (SourceFragmentDefinition s in fks.Select(item => item.SourceFragment).Distinct())
            {
                SourceFragmentDefinition sf = s;

                var targetSF = SourceView.GetSourceFragments().SingleOrDefault(item => item.Name == sf.Name && item.Selector == sf.Selector);

                List <FKDefinition> fksList = new List <FKDefinition>();

                foreach (EntityPropertyDefinition prop in fks.Where(item => item.SourceFragment == sf))
                {
                    EntityDefinition re = prop.PropertyType.Entity;

                    var fpk = re.GetPkProperties().Where(item => prop.SourceFields.Any(fld => fld.PropertyAlias == item.PropertyAlias));
                    if (fpk.Count() == 0)
                    {
                        fpk = re.GetProperties().OfType <ScalarPropertyDefinition>()
                              .Where(item => !item.Disabled && item.SourceField.Constraints.Any(cns => cns.ConstraintType == SourceConstraint.UniqueConstraintTypeName));
                    }

                    FKDefinition f = new FKDefinition
                    {
                        cols    = prop.SourceFields.Select(item => item.SourceFieldExpression).ToArray(),
                        refCols = prop.SourceFields.Select(item => fpk.Single(pk => pk.PropertyAlias == item.PropertyAlias).SourceFieldExpression).ToArray(),
                        refTbl  = fpk.Single(pk => pk.PropertyAlias == prop.SourceFields.First().PropertyAlias).SourceFragment
                    };

                    if (targetSF != null)
                    {
                        if (targetSF.Constraints.Any(item =>
                                                     item.ConstraintType == SourceConstraint.ForeignKeyConstraintTypeName &&
                                                     prop.SourceFields.All(p => item.SourceFields.Any(fkf =>
                                                                                                      fkf.SourceFieldExpression == p.SourceFieldExpression)
                                                                           )
                                                     ))
                        {
                            continue;
                        }
                    }

                    if (string.IsNullOrEmpty(f.constraintName))
                    {
                        f.constraintName = "FK_" + prop.Entity.Name + "_" + re.Name;

                        if (names.Contains(f.constraintName))
                        {
                            f.constraintName += "_" + prop.Name;
                        }
                    }

                    names.Add(f.constraintName);
                    fksList.Add(f);
                }

                if (fksList.Count > 0)
                {
                    if (!hdr)
                    {
                        script.AppendLine("--Creating foreign keys");
                        hdr = true;
                    }
                    provider.GenerateCreateFKsScript(sf, fksList, script);
                }
            }

            foreach (RelationDefinitionBase rel in Model.GetActiveRelations())
            {
                var relSF = SourceView.GetSourceFragments().SingleOrDefault(item => item.Name == rel.SourceFragment.Name && item.Selector == rel.SourceFragment.Selector);
                List <FKDefinition> fksList = new List <FKDefinition>();

                if (rel is SelfRelationDefinition)
                {
                    SelfRelationDefinition r = rel as SelfRelationDefinition;

                    FKDefinition f;
                    if (CreateFKDefinition(r.Properties, r.Left, relSF, script, provider, out f))
                    {
                        fksList.Add(f);
                    }

                    if (string.IsNullOrEmpty(f.constraintName))
                    {
                        f.constraintName = "FK_" + rel.SourceFragment.Name.Trim(']', '[') + "_" + r.Entity.Name;
                    }

                    if (names.Contains(f.constraintName))
                    {
                        f.constraintName += "_" + names.Count(item => item.StartsWith(f.constraintName));
                    }
                    names.Add(f.constraintName);

                    if (CreateFKDefinition(r.Properties, r.Right, relSF, script, provider, out f))
                    {
                        fksList.Add(f);
                    }

                    if (string.IsNullOrEmpty(f.constraintName))
                    {
                        f.constraintName = "FK_" + rel.SourceFragment.Name.Trim(']', '[') + "_" + r.Entity.Name;
                    }

                    if (names.Contains(f.constraintName))
                    {
                        f.constraintName += "_" + names.Count(item => item.StartsWith(f.constraintName));
                    }
                    names.Add(f.constraintName);
                }
                else if (rel is RelationDefinition)
                {
                    RelationDefinition r = rel as RelationDefinition;

                    FKDefinition f;
                    if (CreateFKDefinition(r.Left.Properties, r.Left, relSF, script, provider, out f))
                    {
                        fksList.Add(f);
                    }

                    if (string.IsNullOrEmpty(f.constraintName))
                    {
                        f.constraintName = "FK_" + rel.SourceFragment.Name.Trim(']', '[') + "_" + r.Left.Entity.Name;
                    }

                    if (names.Contains(f.constraintName))
                    {
                        f.constraintName += "_" + names.Count(item => item.StartsWith(f.constraintName));
                    }
                    names.Add(f.constraintName);

                    if (CreateFKDefinition(r.Right.Properties, r.Right, relSF, script, provider, out f))
                    {
                        fksList.Add(f);
                    }

                    if (string.IsNullOrEmpty(f.constraintName))
                    {
                        f.constraintName = "FK_" + rel.SourceFragment.Name.Trim(']', '[') + "_" + r.Right.Entity.Name;
                    }

                    if (names.Contains(f.constraintName))
                    {
                        f.constraintName += "_" + names.Count(item => item.StartsWith(f.constraintName));
                    }
                    names.Add(f.constraintName);
                }
                else
                {
                    throw new NotSupportedException(rel.GetType().ToString());
                }

                if (fksList.Count > 0)
                {
                    if (!hdr)
                    {
                        script.AppendLine("--Creating foreign keys");
                        hdr = true;
                    }
                    provider.GenerateCreateFKsScript(rel.SourceFragment, fksList, script);
                }
            }
        }