private static bool CreateFKDefinition(IEnumerable <ScalarPropertyDefinition> fpk,
                                               SelfRelationTarget rt, SourceFragmentDefinition relSF, StringBuilder script, ISourceProvider provider,
                                               out FKDefinition f)
        {
            f = new FKDefinition()
            {
                cols    = rt.FieldName,
                refCols = fpk.Select(item => item.SourceFieldExpression).ToArray(),
                refTbl  = fpk.First().SourceFragment
            };

            if (relSF != null)
            {
                SourceConstraint fk = relSF.Constraints.SingleOrDefault(item =>
                                                                        item.ConstraintType == SourceConstraint.ForeignKeyConstraintTypeName &&
                                                                        rt.FieldName.All(p => item.SourceFields.Any(pkf => pkf.SourceFieldExpression == p))
                                                                        );

                if (fk != null)
                {
                    //if (!rt.FieldName.All(item => fk.SourceFields.Any(pkf => pkf.SourceFieldExpression == item)))
                    //    provider.GenerateDropConstraintScript(relSF, fk.ConstraintName, script);
                    //else
                    return(false);

                    //f.constraintName = fk.ConstraintName;
                }
            }

            return(true);
        }
        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);
                }
            }
        }