/// <summary>
        /// Gets possible association tables between this entity and the supplied entity.
        /// </summary>
        /// <param name="entity1"></param>
        /// <param name="secondEntity"></param>
        /// <param name="CardinalityPrimary"></param>
        /// <param name="CardinalityForeign"></param>
        /// <returns></returns>
        public static ITable GetAssociationTable(this Entity entity1, Entity secondEntity, out Cardinality CardinalityPrimary, out Cardinality CardinalityForeign, out IKey mainKey, out IKey associationKey)
        {
            CardinalityPrimary = null;
            CardinalityForeign = null;
            mainKey = null;
            associationKey = null;

            ITable associationTable = null;

            foreach (ITable table in entity1.GetMappingSet().Database.AssociationTables())
            {
                //ITable primaryTable = table.Relationships.FirstOrDefault(r => entity1.MappedTables().Contains(r.PrimaryTable));
                bool primaryFound = false;
                bool foreignFound = false;

                #region Primary
                foreach (Relationship relationship in table.Relationships)
                {
                    if (entity1.MappedTables().Contains(relationship.PrimaryTable))
                    {
                        associationTable = table;
                        CardinalityPrimary = relationship.ForeignKey.IsUnique ? Cardinality.One : Cardinality.Many;// relationship.PrimaryCardinality;
                        //CardinalityForeign = relationship.ForeignCardinality;
                        mainKey = relationship.PrimaryKey;
                        //associationKey = relationship.ForeignKey;
                        primaryFound = true;
                        break;
                    }
                    else if (entity1.MappedTables().Contains(relationship.ForeignTable))
                    {
                        associationTable = table;// relationship.ForeignTable;
                        CardinalityPrimary = relationship.PrimaryKey.IsUnique ? Cardinality.One : Cardinality.Many;// relationship.ForeignCardinality;
                        //CardinalityForeign = relationship.PrimaryCardinality;
                        mainKey = relationship.ForeignKey;
                        //associationKey = relationship.PrimaryKey;
                        primaryFound = true;
                        break;
                    }
                }
                #endregion

                #region Foreign
                foreach (Relationship relationship in table.Relationships)
                {
                    if (secondEntity.MappedTables().Contains(relationship.ForeignTable))
                    {
                        associationTable = table;
                        //CardinalityPrimary = relationship.PrimaryCardinality;
                        CardinalityForeign = relationship.PrimaryKey.IsUnique ? Cardinality.One : Cardinality.Many;// relationship.ForeignCardinality;
                        //mainKey = relationship.PrimaryKey;
                        associationKey = relationship.ForeignKey;
                        foreignFound = true;
                        break;
                    }
                    else if (secondEntity.MappedTables().Contains(relationship.PrimaryTable))
                    {
                        //associationTable = table;// relationship.ForeignTable;
                        //CardinalityPrimary = relationship.ForeignCardinality;
                        CardinalityForeign = relationship.ForeignKey.IsUnique ? Cardinality.One : Cardinality.Many;// relationship.PrimaryCardinality;
                        //mainKey = relationship.ForeignKey;
                        associationKey = relationship.PrimaryKey;
                        foreignFound = true;
                        break;
                    }
                }
                #endregion

                if (primaryFound && foreignFound)
                {
                    break;
                }
                else
                {
                    associationTable = null;
                    CardinalityPrimary = null;
                    CardinalityForeign = null;
                    mainKey = null;
                    associationKey = null;
                }

                //                if (entity1.MappedTables().Contains(relationship.PrimaryTable))// &&
                //                //secondEntity.MappedTables().Contains(relationship.ForeignTable))
                //                {
                //                    associationTable = table;// relationship.PrimaryTable;
                //                    CardinalityPrimary = relationship.PrimaryCardinality;
                //                    CardinalityForeign = relationship.ForeignCardinality;
                //                    mainKey = relationship.PrimaryKey;
                //                    associationKey = relationship.ForeignKey;

                //                    if (oneFound)
                //                        break;
                //                    else
                //                        oneFound = true;
                //                }
                //                else if (entity1.MappedTables().Contains(relationship.ForeignTable) &&
                //secondEntity.MappedTables().Contains(relationship.PrimaryTable))
                //                {
                //                    associationTable = table;// relationship.ForeignTable;
                //                    CardinalityPrimary = relationship.ForeignCardinality;
                //                    CardinalityForeign = relationship.PrimaryCardinality;
                //                    mainKey = relationship.ForeignKey;
                //                    associationKey = relationship.PrimaryKey;

                //                    if (oneFound)
                //                        break;
                //                    else
                //                        oneFound = true;
                //                }
                //}
            }
            if (associationTable != null)
                return associationTable;

            ITable unpureAssociationTable = null;

            if (associationTable == null)
            {
                foreach (ITable table in entity1.MappedTables())
                {
                    foreach (Relationship relationship in table.Relationships)
                    {
                        ITable possibleAssociationTable = null;

                        if (entity1.MappedTables().Contains(relationship.PrimaryTable) &&
                            Cardinality.IsOneToMany(relationship.ForeignCardinality, relationship.PrimaryCardinality))
                        {
                            possibleAssociationTable = relationship.ForeignTable;
                            CardinalityPrimary = relationship.PrimaryCardinality;
                            mainKey = relationship.ForeignKey;
                        }
                        else if (entity1.MappedTables().Contains(relationship.ForeignTable) &&
                            Cardinality.IsOneToMany(relationship.PrimaryCardinality, relationship.ForeignCardinality))
                        {
                            possibleAssociationTable = relationship.PrimaryTable;
                            CardinalityPrimary = relationship.ForeignCardinality;
                            mainKey = relationship.PrimaryKey;
                        }
                        if (possibleAssociationTable != null)
                        {
                            foreach (ITable otherTable in secondEntity.MappedTables())
                            {
                                foreach (Relationship otherRelationship in otherTable.Relationships.Where(r => r.PrimaryTable == possibleAssociationTable || r.ForeignTable == possibleAssociationTable))
                                {
                                    if (otherRelationship.PrimaryTable == otherTable &&
                                        Cardinality.IsOneToMany(otherRelationship.ForeignCardinality, otherRelationship.PrimaryCardinality) &&
                                        possibleAssociationTable.Relationships.Where(r => r.PrimaryTable == otherRelationship.ForeignTable || r.ForeignTable == otherRelationship.ForeignTable).Count() > 0)
                                    {
                                        unpureAssociationTable = otherRelationship.ForeignTable;
                                        CardinalityForeign = otherRelationship.PrimaryCardinality;
                                        associationKey = otherRelationship.ForeignKey;
                                        return unpureAssociationTable;
                                    }
                                    else if (otherRelationship.ForeignTable == otherTable &&
                                             Cardinality.IsOneToMany(otherRelationship.PrimaryCardinality, otherRelationship.ForeignCardinality) &&
                                             possibleAssociationTable.Relationships.Where(r => r.PrimaryTable == otherRelationship.PrimaryTable || r.ForeignTable == otherRelationship.PrimaryTable).Count() > 0)
                                    {
                                        unpureAssociationTable = otherRelationship.PrimaryTable;
                                        CardinalityForeign = otherRelationship.ForeignCardinality;
                                        associationKey = otherRelationship.PrimaryKey;
                                        return unpureAssociationTable;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return null;
        }
 private void Clear()
 {
     CardinalityPrimary = null;
     CardinalityForeign = null;
     AssociationTable = null;
     SelectedRelationship = null;
 }
        private bool IsSelectionValidForEntityRequestor(Entity selectedEntity)
        {
            List<ITable> selectedEntitiesTables = selectedEntity.MappedTables().ToList();
            List<Relationship> validRelationships = new List<Relationship>();
            List<ITable> validAssociationTables = new List<ITable>();

            if (selectedEntitiesTables.Count == 1 &&
                Entity.MappedTables().Count() == 1 &&
                selectedEntitiesTables[0] == Entity.MappedTables().ElementAt(0))
            {
                // Table Per Hierarchy inheritance
                return true;
            }
            if (RequestorType == RequestorTypes.Entity_Select_Parent &&
                selectedEntitiesTables.Count == 0)
            {
                bool isOk = true;

                foreach (Property property in selectedEntity.Properties)
                {
                    if (Entity.Properties.Count(p => p.Name == property.Name && p.Type == property.Type) == 0)
                    {
                        isOk = false;
                        break;
                    }
                }
                // This is OK for Table Per Concrete Class inheritance - the Base is totally virtual and doesn't have
                // a mapped table in the database, and all of it's properties exist in the child class.
                if (isOk)
                    return true;
            }
            else if (RequestorType == RequestorTypes.Entity_Select_Child && selectedEntitiesTables.Count > 0)
            {
                bool isOk = true;

                foreach (Property property in Entity.Properties)
                {
                    if (selectedEntity.Properties.Count(p => p.Name == property.Name && p.Type == property.Type) == 0)
                    {
                        isOk = false;
                        break;
                    }
                }
                // This is OK for Table Per Concrete Class inheritance - the Base is totally virtual and doesn't have
                // a mapped table in the database, and all of it's properties exist in the child class.
                if (isOk)
                    return true;
            }
            if (SelectedRelationship != null)
                return true;

            // Check that a relationship or association table exists between the entity and the new selected entity
            foreach (ITable table in Entity.MappedTables())
            {
                foreach (Relationship relationship in table.Relationships)
                {
                    if (selectedEntitiesTables.Contains(relationship.PrimaryTable) ||
                        selectedEntitiesTables.Contains(relationship.ForeignTable))
                    {
                        validRelationships.Add(relationship);
                        SelectedRelationship = relationship;

                        if (table == relationship.PrimaryTable)
                        {
                            CardinalityPrimary = relationship.PrimaryCardinality;
                            CardinalityForeign = relationship.ForeignCardinality;
                        }
                        else
                        {
                            CardinalityPrimary = relationship.ForeignCardinality;
                            CardinalityForeign = relationship.PrimaryCardinality;
                        }
                        break;
                    }
                }
                if (SelectedRelationship != null)
                    break;
            }
            IKey primaryKey = null;
            IKey foreignKey = null;
            ITable associationTable = null;

            if (validRelationships.Count == 0)
                associationTable = Entity.GetAssociationTable(selectedEntity, out CardinalityPrimary, out CardinalityForeign, out primaryKey, out foreignKey);

            if (validRelationships.Count == 0 &&
                associationTable == null)
            {
                //MessageBox.Show(this, string.Format("No relationships or association tables exist between {0} and {1}.{2}You need to add a relationship (or association table) between the tables in the database, or add a virtual relationship between these tables in the table-diagrammer.",
                //    Entity.Name,
                //    selectedEntity.Name,
                //    Environment.NewLine), "No valid relationships", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                //Close();
                //return;
                return false;
            }
            if (associationTable != null)
                AssociationTable = associationTable;

            return true;
        }
        private void buttonOk_Click(object sender, EventArgs e)
        {
            SelectedEntities = new List<Entity>();

            if (checkBoxCreateNewEntity.Checked || RequestorType == RequestorTypes.Entity_Create_Abstract_Parent)
            {
                if (!CreateNewEntity())
                    return;
            }
            else
            {
                if (SelectedItems.Count > 0)
                {
                    List<string> invalidSelections = new List<string>();

                    foreach (ListViewItem item in SelectedItems)
                    {
                        Entity entity = null;

                        if (item.Tag is Entity)
                            entity = (Entity)item.Tag;
                        else if (item.Tag is EntityRelationshipContainer)
                        {
                            EntityRelationshipContainer keyValue = (EntityRelationshipContainer)item.Tag;
                            entity = keyValue.Entity;
                            SelectedRelationship = keyValue.Relationship;

                            CardinalityPrimary = SelectedRelationship.PrimaryCardinality;
                            CardinalityForeign = SelectedRelationship.ForeignCardinality;

                        }
                        else
                            throw new NotImplementedException("Not handled yet: " + item.Tag.GetType().Name);

                        if (RequestorType == RequestorTypes.Entity_Select_Existing ||
                            RequestorType == RequestorTypes.Entity_Select_Child ||
                            RequestorType == RequestorTypes.Entity_Select_Parent)
                        {
                            if (IsSelectionValidForEntityRequestor(entity))
                                SelectedEntities.Add(entity);
                            else
                                invalidSelections.Add(entity.Name);
                        }
                        else
                            SelectedEntities.Add(entity);
                    }
                    if (invalidSelections.Count > 0)
                    {
                        StringBuilder sb = new StringBuilder();

                        foreach (string invalidSelection in invalidSelections)
                            sb.Append(invalidSelection + ", ");

                        MessageBox.Show(this, string.Format("No relationships or association tables exist between {0} and:{2}{1}.{2}You need to add a relationship (or association table) between the tables in the database, or add a virtual relationship between these tables in the table-diagrammer.",
                            Entity.Name,
                            sb.ToString().Trim(',', ' '),
                            Environment.NewLine), "No valid relationships", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    }
                }
                else
                    return;

                if (SelectedEntity == null && !MultiSelect && SelectedEntities.Count > 0)
                    SelectedEntity = SelectedEntities[0];

                if (RequestorType == RequestorTypes.Entity_Select_Parent &&
                    SelectedEntity.MappedTables().Count() == 0)
                {
                    // This is a Table Per Concrete Class inheritance, so remove the matching properties from the child.
                    foreach (Property property in SelectedEntity.Properties)
                    {
                        Property childProperty = Entity.Properties.SingleOrDefault(p => p.Name == property.Name && p.Type == property.Type);

                        if (childProperty == null)
                            throw new Exception("This is meant to be a TPCC inheritance, but no matching property was found in the child.");

                        Entity.RemoveProperty(childProperty);
                    }
                }
            }
            if (!MultiSelect)
                if (SelectedEntities.Count > 0)
                    SelectedEntity = SelectedEntities[0];
            //else
            //	SelectedEntity = null;

            Close();
        }