// set related name (for Designer class) // (late call by Builder.AppendMapperNamespace method) internal string GetRelatedNameForDesigner_DEPR(TableOrView related) { string name; // related is the same node (self relation) if (IsSelf) { name = ClrName.SELF; } // related is other node else { name = ((IName)related).NodeName; } if (RenameIndexForDesigner > 0) { return(String.Format("{0}{1}{2}", name, ClrName.RENAMED, RenameIndexForDesigner > 1 ? RenameIndexForDesigner.ToString() : "")); } else { return(name); } }
// provide unique related name (for Designer class) // return foreign key column (or null) : foreign key is needed (in case of multiple relations) internal static Column ProvideUniqueNameForDesigner(Relation relation, TableOrView node, TableOrView related, HashSet <string> names) { // set related node name int i = 1; while (true) { // get related name //var relatedName = relation.GetRelatedNameForDesigner(related); var relatedName = relation.GetRelatedNameForDesigner(node, related); // check uniqueness if (relatedName == ((IName)node).NodeName || !(names.Add(relatedName))) { relation.RenameIndexForDesigner = i; } else // ok { relation.RelatedNameForDesigner = relatedName; // set related name break; } ++i; } // return foreign key (null if not exposed) return(relation.ExposedForeignKeyColumn); }
// provide unique related name (for Data class) internal static void ProvideUniqueNameForData(Relation relation, TableOrView node, TableOrView related, HashSet <string> names) { // set related node name int i = 1; while (true) { // get related name var relatedName = relation.GetRelatedNameForData(node, related); // check uniqueness //if (!(names.Add(relatedName.ToUpperInvariant()))) if (relatedName == ((IName)node).NodeName || !(names.Add(relatedName))) { relation.RenameIndexForData = i; } else // ok { relation.RelatedNameForData = relatedName; // set related name break; } ++i; } }
// set exposed foreign key and returns FK node (in case of many relations) private void SetForeignKey(TableOrView node, TableOrView related) { if (HAS_MANY) { if (!IsMirrored) { ExposedForeignKeyColumn = node.Columns[ForeignKeyOrdinal - 1]; } else { ExposedForeignKeyColumn = related.Columns[ForeignKeyOrdinal - 1]; } } }
// get related name (for Data class) // (late call by Builder.AppendMapperNamespace method) internal string GetRelatedNameForData(TableOrView node, TableOrView related) { string name; // related is the same node (self relation) if (IsSelf) { name = ClrName.SELF; } // related is other node else { name = ((IName)related).NodeName; } // set foreign key SetForeignKey(node, related); // rename index int?index = null; if (RenameIndexForData > 0) { if (_hasExposedForeignKey) { index = RenameIndexForData + 1; // ByForeignKey2 } else if (RenameIndexForData > 1) { index = RenameIndexForData; // TableRenamed } } if (_hasExposedForeignKey) { return(String.Format("{0}By{1}{2}", name, ExposedForeignKey, index)); } else if (RenameIndexForData > 0) { return(String.Format("{0}{1}{2}", name, ClrName.RENAMED, index)); } else { return(name); } }
private void _AppendDesignerColumns(TableOrView table) { foreach (var column in table.OrderedColumns) // ordered by name { _csharp.AppendFormatLine("nodeMap.Columns.Add(new QueryTalk.Wall.ColumnMap(_NodeID.GetColumnID(" + "{0}), {8}, \"{1}\".I(false), {2}, {3}, {4}, {5}, {6}, QueryTalk.Wall.ColumnType.{7}, {9}));", ((INode)column).NodeID, column.COLUMN_NAME.EscapeDoubleQuote(), column.TypeInfo.BuildDbt(column.LENGTH, column.PRECISION, column.SCALE), column.IS_NULLABLE.ToClrString(), column.IS_RK.ToClrString(), column.IS_UK.ToClrString(), column.IS_FK.ToClrString(), column.ColumnType, column.ORDINAL_POSITION, column.HAS_DEFAULT.ToClrString()); } }
private void _AppendDesignerRelations(TableOrView table, HashSet <string> columnSet) { // relations if (table.Relations != null) { // loop thru relations foreach (var relation in table.Relations) // .Where(r => r.IsLink)) DEPRECATED: Data & Design classes have the same structure { // check if relation is compliant if (!IsRelationCompliant(relation)) { continue; } // related node var related = TableObjects[relation.RELATED_ID]; // set related node name (as unique) var foreignKey = ClrName.ProvideUniqueNameForDesigner(relation, table, related, columnSet); if (foreignKey != null) { _csharp.AppendFormatLine("public {0}<TRoot> {1} {{ get {{", // return new {0}<TRoot>(this, {2}); }} }}", ((IName)related).NodeName, relation.RelatedNameForDesigner); _csharp.AppendFormatLine("var r = new {0}<TRoot>(this);", ((IName)related).NodeName); // get fk node TableOrView fknode = !relation.IsMirrored ? table : related; _csharp.AppendFormatLine("((QueryTalk.Wall.IRelation)r).FK = {0}<TRoot>._NodeID.GetColumnID({1});", ((IName)fknode).NodeName, ((INode)relation.ExposedForeignKeyColumn).NodeID); _csharp.AppendLine("return r;"); _csharp.AppendLine("}}"); } else { _csharp.AppendFormatLine("public {0}<TRoot> {1} {{ get {{ return new {0}<TRoot>(this); }} }}", ((IName)related).NodeName, relation.RelatedNameForDesigner); } } } }
private void _AppendDataRelations(TableOrView table, HashSet <string> columnSet) { // relations if (table.Relations != null) { // loop through publicly exposed relations Relation prev = null; foreach (var relation in table.Relations) // .OrderByDescending(r => r.IsLink)) // DEPRECATED (NOT NEEDED) { // check if relation is compliant if (!IsRelationCompliant(relation)) { continue; } // related node var related = TableObjects[relation.RELATED_ID]; // set related node name (as unique) ClrName.ProvideUniqueNameForData(relation, table, related, columnSet); if (relation.IsOneToMany()) { // MANY PROPERTY _csharp.AppendFormatLine("public System.Collections.Generic.HashSet<{0}> {1} {{ get; set; }}", ((IName)related).NodeName, relation.RelatedNameForData); } else { _csharp.AppendFormatLine("public {0} {1} {{ get; set; }}", ((IName)related).NodeName, relation.RelatedNameForData); } prev = relation; } } }
// process relations private void ProcessRelations() { // prepare relations (append columns) int t = 0; // index of tables int tp = -1; // index of previous table var tables = DbInfo.Table1 .Where(a => (ObjectType)a.OBJECT_TYPE == ObjectType.Table) .OrderBy(a => a.OBJECT_ID) .ToList(); // columns int c = 0; // index of relation columns var columns = DbInfo.Table6 .OrderBy(a => a.NODE_ID) .ThenBy(a => a.RELATED_ID) .ThenBy(a => a.RELATION_ID) .ThenBy(a => a.IsMirrored) .ToList(); var cc = columns.Count - 1; // columns count // loop through RELATIONS TableOrView table = null; int rid = -1; // previous related node Relation prev = null; // previous relation (of the same link) foreach (var relation in DbInfo.Table5 .OrderBy(a => a.NODE_ID) .ThenBy(a => a.RELATED_ID) .ThenBy(a => a.RELATION_ID) .ThenBy(a => a.MirroringIndex)) { // find table of relation while (tables[t].OBJECT_ID < relation.NODE_ID) { ++t; } // ATTENTION! We anticipate that we must have found the table (!) - no failure here. // (Since ALL the tables are included in the 'tables' collection.) // now find the relation column while (!( columns[c].NODE_ID == relation.NODE_ID && columns[c].RELATED_ID == relation.RELATED_ID && columns[c].RELATION_ID == relation.RELATION_ID && columns[c].IsMirrored == relation.MirroringIndex)) { ++c; } // ATTENTION! We anticipate that we must have found the first matching column (!) - no failure here // loop through the columns and include them in the relation object relation.Columns = new List <RelationColumn>(); while ( columns[c].NODE_ID == relation.NODE_ID && columns[c].RELATED_ID == relation.RELATED_ID && columns[c].RELATION_ID == relation.RELATION_ID && columns[c].IsMirrored == relation.MirroringIndex) { relation.Columns.Add(columns[c]); ++c; // check if (c > cc) { break; } } // we assume that this is THE FIRST RELATION of the link relation.IsLink = true; // is new node if (t != tp) { table = tables[t]; table.Relations = new List <Relation>(); tp = t; } // establish a connecton between the current relation and the next relation of the same link (multiple relations) else if (rid == relation.RELATED_ID && prev.RELATION_TYPE == relation.RELATION_TYPE) // Only the familiar relation type (to support cross relations) { prev.Next = relation; // if a relation has a predecessor => it cannot be the first relation relation.IsLink = false; } // add relation to table table.Relations.Add(relation); // set next relation handler's variables rid = relation.RELATED_ID; prev = relation; } }
private Column _GetRKColumn(Relation relation, TableOrView rnode, int c) { return(relation.GetForeignColumn(rnode, relation.Columns[c].RELATED_COLUMN_ORDINAL)); }
private Column _GetFKColumn(Relation relation, TableOrView fknode, int c) { return(relation.GetForeignColumn(fknode, relation.Columns[c].COLUMN_ORDINAL)); }
private void _AppendDesignerLinks(TableOrView table) { // check if any relations if (table.Relations == null) { return; } int i = 0; int related_id = -1; foreach (var relation in table.Relations.OrderBy(r => r.RELATED_ID)) { // check if relation is compliant if (!IsRelationCompliant(relation)) { continue; } var related = TableObjects[relation.RELATED_ID]; // is new link if (related_id != relation.RELATED_ID) { ++i; _csharp.AppendFormatLine("var id{0} = QueryTalk.Wall.DB3.Get({1}.Map.ID.DbX, {2}, 0);", i, _dbName, ((INode)related).NodeID); _csharp.AppendFormatLine("var link{0} = QueryTalk.Wall.Api.AddLink(new QueryTalk.Wall.Link(_NodeID, id{0}));", i); related_id = relation.RELATED_ID; // append AddNodeInvoker (if not self relation) if (!relation.IsSelf) { _csharp.AppendFormatLine("QueryTalk.Wall.Api.AddNodeInvoker(new QueryTalk.Wall.NodeInvoker(id{0}, () => {{ var x = {1}<TRoot>._NodeID; }}));", i, ((IName)related).NodeName); } } // build relations var fkColumnZ = relation.GetForeignKeyColumnsZ(TableObjects); string fkBuild = null, fkColumnsBuild = null, rkColumnsBuild = null; fkColumnsBuild = String.Format("new[] {{{0}}}", String.Join(",", relation.Columns.Select(c => String.Format("_NodeID.GetColumnID({0})", ((INode)table.Columns[c.COLUMN_ORDINAL - 1]).NodeID)))); rkColumnsBuild = String.Format("new[] {{{0}}}", String.Join(",", relation.Columns.Select(c => String.Format("id{0}.GetColumnID({1})", i, ((INode)related.Columns[c.RELATED_COLUMN_ORDINAL - 1]).NodeID)))); // FK->RK if (relation.IsFromFKToRK()) { fkBuild = String.Format("_NodeID.GetColumnID({0})", fkColumnZ); _csharp.AppendFormatLine("link{0}.AddRelation(new QueryTalk.Wall.Relation({1}, {2}, {3}));", i, fkBuild, fkColumnsBuild, rkColumnsBuild); _csharp.AppendFormatLine("QueryTalk.Wall.Api.AddGraphInvoker(Invokers.GetGraphInvoker_{0}(_NodeID.GetColumnID({1}), id{2}));", relation.RELATION_ID, fkColumnZ, i); } // RK->FK => reverse collections else { fkBuild = String.Format("id{0}.GetColumnID({1})", i, fkColumnZ); _csharp.AppendFormatLine("link{0}.AddRelation(new QueryTalk.Wall.Relation({1}, {2}, {3}));", i, fkBuild, rkColumnsBuild, fkColumnsBuild); _csharp.AppendFormatLine("QueryTalk.Wall.Api.AddGraphInvoker(Invokers.GetGraphInvoker_{0}(id{1}.GetColumnID({2}), _NodeID));", relation.RELATION_ID, i, fkColumnZ); } } }
private void _AppendDataInsertChildren(TableOrView table) { // method signature _csharp.AppendFormatLine("internal static void InsertChildren(System.Reflection.Assembly client, System.Collections.Generic.IEnumerable<{0}> parents, QueryTalk.Wall.ConnectBy connectBy) {{", ((IName)table).NodeName); // check if any RK->FK relation if (table.Relations == null || !table.Relations.Exists(r => r.IsFromRKToFK())) { _csharp.AppendLine("}"); return; } /* * cs1: var cc1 = new HashSet<Person>(); * cs2: foreach (var child in parent.Persons) { child.CountryOfBirthID = parent.CountryID; cc1.Add(child); } * cs3: QueryTalk.Wall.Crud.GoInsertRows(client, cc1, false, connectBy); * Person.InsertChildren(client, cc1, connectBy); */ var cs1 = new StringBuilder(); var cs2 = new StringBuilder(); var cs3 = new StringBuilder(); var i = 1; foreach (var relation in table.Relations //.Where(r => r.IsLink) // DEPRECATED .Where(r => r.IsFromRKToFK())) { // check if relation is compliant if (!IsRelationCompliant(relation)) { continue; } // get related var related = TableObjects[relation.RELATED_ID]; relation.RelatedName = ((IName)related).NodeName; var relatedNameForData = relation.RelatedNameForData; // cs1 cs1.AppendFormatLine("var cc{0} = new System.Collections.Generic.HashSet<{1}>();", i, relation.RelatedName); // cs2 //if (!relation.IsOneToSingle()) if ((RelationType)relation.RELATION_TYPE != RelationType.OneToSingle) { cs2.AppendFormatLine("if (parent.{0} != null) {{", relatedNameForData); cs2.AppendFormatLine("foreach (var child in parent.{0}) {{", relatedNameForData); // foreach child Relation rel = relation; foreach (var column in rel.Columns) { cs2.AppendFormatLine("child.{0} = parent.{1};", ((IName)related.Columns[column.RELATED_COLUMN_ORDINAL - 1]).NodeName, ((IName)table.Columns[column.COLUMN_ORDINAL - 1]).NodeName); } cs2.AppendFormatLine("cc{0}.Add(child);", i); cs2.AppendLine("}"); // end of foreach child cs2.AppendLine("}"); // end of if } // add relation OneToSingle else { cs2.AppendFormatLine("if (parent.{0} != null) {{", relatedNameForData); foreach (var column in relation.Columns) { cs2.AppendFormatLine("parent.{0}.{1} = parent.{2};", relatedNameForData, ((IName)related.Columns[column.RELATED_COLUMN_ORDINAL - 1]).NodeName, ((IName)table.Columns[column.COLUMN_ORDINAL - 1]).NodeName); } cs2.AppendFormatLine("cc{0}.Add(parent.{1});", i, relatedNameForData); cs2.AppendLine("}"); } // cs3 string isIdentity = "false"; if ((RelationType)relation.RELATION_TYPE == RelationType.OneToSingle) { isIdentity = "true"; } cs3.AppendFormatLine("QueryTalk.Wall.Crud.InsertRowsGo(client, cc{0}, {1}, connectBy);", i, isIdentity); cs3.AppendFormatLine("{2}.{0}.InsertChildren(client, cc{1}, connectBy);", relation.RelatedName, i, DataNamespace); ++i; } // final build _csharp .AppendLine(cs1.ToString()) .AppendLine("foreach (var parent in parents) {") .AppendLine(cs2.ToString()) .AppendLine("}") .AppendLine(cs3.ToString()) .AppendLine("}"); // end of method }
// return the column that is a part of a FK internal Column GetForeignColumn(TableOrView fknode, int ordinal) { return(fknode.Columns[ordinal - 1]); }
// foreign key of this relation // param // fknode : FK table of this relation internal Column GetForeignKey(TableOrView fknode) { return(fknode.Columns[ForeignKeyOrdinal - 1]); }