示例#1
0
        internal static string GetForeignKeyName(DB3 foreignKey)
        {
            ColumnMap foreignKeyMap;
            string    foreignKeyFullName = Text.Unknown;

            if (!foreignKey.Equals(DB3.Default))
            {
                foreignKeyMap      = GetColumnMap(foreignKey);
                foreignKeyFullName = foreignKeyMap.FullName;
            }

            return(foreignKeyFullName);
        }
示例#2
0
        internal Relation TryGetRelation(DB3 foreignKey, string method = null)
        {
            if (HasIntermediate)
            {
                throw new QueryTalkException("Link.TryGetRelation", QueryTalkExceptionType.IntermediateTableDisallowed,
                                             String.Format("linked tables = {0}:{1}{2}   intermediate table = {3}",
                                                           DbMapping.GetNodeMap(TableA).Name.Sql,
                                                           DbMapping.GetNodeMap(TableB).Name.Sql,
                                                           Environment.NewLine, DbMapping.GetNodeMap(Intermediate).Name.Sql),
                                             method);
            }

            Relation relation = null;

            if (foreignKey.Equals(DB3.Default))
            {
                // single relation
                if (_relations.Count == 1)
                {
                    return(_relations.First());
                }
                // many relations - missing FK
                else
                {
                    throw new QueryTalkException("Link.TryGetRelation", QueryTalkExceptionType.MissingForeignKey,
                                                 String.Format("linked tables = {0}:{1}",
                                                               DbMapping.GetNodeMap(TableA).Name.Sql,
                                                               DbMapping.GetNodeMap(TableB).Name.Sql), method);
                }
            }
            // foreign key is defined:
            else
            {
                relation = _relations.Where(a => a.FKColumns.Contains(foreignKey))
                           .FirstOrDefault();

                if (relation == null)
                {
                    DbMapping.ThrowForeignKeyNotFoundException(foreignKey, TableA);
                }
            }

            return(relation);
        }
示例#3
0
        // builds a relation SQL clause
        internal static Relation GetRelation(DB3 tableA, DB3 tableB, DB3 foreignKey, string method = null)
        {
            var link = TryFindLink(tableA, tableB, method);

            if (foreignKey.Equals(DB3.Default))
            {
                if (link.HasManyRelations)
                {
                    throw new QueryTalkException("DbMapping.BuildRelation", QueryTalkExceptionType.MissingForeignKey,
                                                 String.Format("linked tables = {0}:{1}", GetNodeMap(tableA).Name.Sql, GetNodeMap(tableB).Name.Sql), method);
                }
                else
                {
                    foreignKey = link.DefaultForeignKey;
                }
            }

            return(link.TryGetRelation(foreignKey, method));
        }
示例#4
0
        internal static Link TryFindLink(DB3 tableA, DB3 tableB, string method = null)
        {
            var link = GetLink(tableA, tableB);

            if (link == null && !tableA.Equals(tableB))
            {
                link = TryFindIntermediate(tableA, tableB, method);
            }

            // second check
            if (link == null)
            {
                throw new QueryTalkException("DbMapping.TryFindLink", QueryTalkExceptionType.LinkNotFound,
                                             String.Format("table A = {0}{1}   table B = {2}",
                                                           DbMapping.GetNodeMap(tableA).Name.Sql, Environment.NewLine,
                                                           DbMapping.GetNodeMap(tableB).Name.Sql),
                                             method);
            }

            return(link);
        }
示例#5
0
 // returns true if the table is on foreign key side in the relationship
 internal bool IsFKTable(DB3 table)
 {
     return(table.Equals(FKTable));
 }
示例#6
0
 // returns true if the table is on reference side in the relationship
 internal bool IsRefTable(DB3 table)
 {
     return(table.Equals(RefTable));
 }
示例#7
0
        // try find intermediate table & cache it
        private static Link TryFindIntermediate(DB3 tableA, DB3 tableB, string method = null)
        {
            // do not seek for link between the equal tables
            if (!tableA.Equals(tableB))
            {
                // find all (ordered) links of tableA
                var linksA = _orderedLinks.Where(a => a.TableA.Equals(tableA));

                // find all (ordered) links of tableB
                var linksB = _orderedLinks.Where(a => a.TableA.Equals(tableB));

                // find all intermediate tables
                var intermediates =
                    (from a in linksA
                     join b in linksB on a.TableB equals b.TableB
                     select a.TableB).ToList();

                // enumerate through each intermediate table and evaluate it
                DB3 c  = DB3.Default;   // first intermediate
                DB3 c2 = DB3.Default;   // superfluous intermediate (should not exists)
                foreach (var intermediate in intermediates)
                {
                    // make sure that the table has been initialized
                    _Invoke(intermediate);

                    // get link C to A
                    var linkToA = _orderedLinks
                                  .Where(a => a.TableA.Equals(intermediate) &&
                                         a.TableB.Equals(tableA))
                                  .Select(a => a.Link)
                                  .Distinct()
                                  .FirstOrDefault();

                    // get link C to B
                    var linkToB = _orderedLinks
                                  .Where(a => a.TableA.Equals(intermediate) &&
                                         a.TableB.Equals(tableB))
                                  .Select(a => a.Link)
                                  .Distinct()
                                  .FirstOrDefault();

                    // exclude intermediates that have links with many relations
                    if (linkToA.HasManyRelations || linkToB.HasManyRelations)
                    {
                        continue;
                    }

                    // There are 4 combinations of A.C.B relationship:
                    // --------------------------------------------------
                    //   A << C >> B    (allowed)
                    //   A << C << B    (allowed)
                    //   A >> C >> B    (allowed)
                    //   A >> C << B    (disallowed)
                    // -------------------------------------------------------------------------
                    // The intermediate tables that on ONE side of both relations are excluded.
                    // -------------------------------------------------------------------------
                    if (linkToA.IsRefTable(intermediate) && linkToB.IsRefTable(intermediate))
                    {
                        continue;
                    }

                    if (c.IsDefault)
                    {
                        c = intermediate;
                    }
                    else
                    {
                        c2 = intermediate;
                    }
                }

                // hit
                if (!c.IsDefault)
                {
                    // only a single intermediate table is allowed
                    if (c2.IsDefault)
                    {
                        // create and cache the link A:B
                        var link = new Link(tableA, tableB, c);
                        _links.Add(link);
                        return(link);
                    }
                    else
                    {
                        // link ambiguity
                        throw new QueryTalkException("DbMapping.TryFindIntermediate", QueryTalkExceptionType.LinkAmbiguity,
                                                     String.Format("table A = {0}{1}   table B = {2}{3}   intermediate 1 = {4}{5}   intermediate 2 = {6}",
                                                                   GetNodeMap(tableA).Name.Sql, Environment.NewLine,
                                                                   GetNodeMap(tableB).Name.Sql, Environment.NewLine,
                                                                   GetNodeMap(c).Name.Sql, Environment.NewLine,
                                                                   GetNodeMap(c2).Name.Sql),
                                                     method).SetObjectName(DbMapping.GetNodeMap(tableA).Name.Sql);
                    }
                }
            }

            // link has not been found
            throw new QueryTalkException("DbMapping.TryFindIntermediate",
                                         QueryTalkExceptionType.LinkNotFound,
                                         String.Format("table A = {0}{1}   table B = {2}",
                                                       GetNodeMap(tableA).Name.Sql, Environment.NewLine, GetNodeMap(tableB).Name.Sql),
                                         method).SetObjectName(DbMapping.GetNodeMap(tableA).Name.Sql);
        }