/// <summary> /// Construct a new MappingTable /// </summary> public MappingTable(Relation parent) : base(parent) { }
private void GenerateMappingTable(NDO.Mapping.Class parentClass, NDO.Mapping.Class relClass, NDO.Mapping.Relation r, DataTable parentTable) { //MM 6 ggf. Tabelle anlegen // Gibt's die Table schon in dsSchema? // Nein: Anlegen DataTable dtMap; if (!dsSchema.Tables.Contains(r.MappingTable.TableName)) { dsSchema.Tables.Add(dtMap = new DataTable(r.MappingTable.TableName)); } else { dtMap = dsSchema.Tables[r.MappingTable.TableName]; } //MM 7 ForeignKey-Spalten für eigene und Fremdklasse anlegen //MM 7 Wenn nötig auch die TypeColumns anlegen // Addiere die Spalte r.ForeignKeyColumnName new ForeignKeyIterator(r).Iterate(delegate(ForeignKeyColumn fkColumn, bool isLastElement) { SearchAndAddColumn(dtMap, fkColumn.Name, fkColumn.SystemType); }); // Lege ggf. die Typspalte an, Typ ist immer int if (r.ForeignKeyTypeColumnName != null) { SearchAndAddColumn(dtMap, r.ForeignKeyTypeColumnName, typeof(int)); } // Addiere die Spalte r.MappingTable.ChildForeignKeyColumnName new ForeignKeyIterator(r.MappingTable).Iterate(delegate(ForeignKeyColumn fkColumn, bool isLastElement) { SearchAndAddColumn(dtMap, fkColumn.Name, fkColumn.SystemType); }); #if nix // Old single column code Type defaultType = null; //TODO: Interfaces berücksichtigen if (relClass == null) // Interface { // Typ ist Interface throw new NotImplementedException("Interface"); } else { defaultType = relClass.Oid.FieldType; } searchAndAddColumn(dtMap, r.MappingTable.ChildForeignKeyColumnName, defaultType); #endif if (r.MappingTable.ChildForeignKeyTypeColumnName != null) { SearchAndAddColumn(dtMap, r.MappingTable.ChildForeignKeyTypeColumnName, typeof(int)); } }
/// <summary> /// Removes a relation from the Class object. /// </summary> /// <param name="r"></param> public void AddRelation(Relation r) { r.SetParent(this); this.relations.Add(r); this.Changed = true; }
void CheckRelation(Test test, RelInfo ri) { if (!ri.HasTable) { return; } NDO.Mapping.Class clMapping = mapping.FindClass("RelationTestClasses." + test.OwnClass.Name); if (clMapping == null) { return; } NDO.Mapping.Relation rel = (NDO.Mapping.Relation)clMapping.Relations.FirstOrDefault(); Debug.Assert(rel != null, "Relation mapping not found"); if (rel == null) { throw new Exception("Cant find relation 0 of" + test.OwnClass.Name); } NDO.Mapping.Class derivedMapping; NDO.Mapping.Relation derivedRel = null; if (ri.OwnPoly) { derivedMapping = mapping.FindClass("RelationTestClasses." + test.OwnDerivedClass.Name); if (derivedMapping == null) { return; } derivedRel = (NDO.Mapping.Relation)derivedMapping.Relations.FirstOrDefault(); if (rel == null) { throw new Exception("Cant find relation 0 of" + test.OwnDerivedClass.Name); } } if (rel.MappingTable == null || ri.OwnPoly && derivedRel.MappingTable == null) { string tableName = null; if (test.OwnClass.Name.CompareTo(test.OtherClass.Name) < 0) { tableName = "rel" + test.OwnClass.Name + test.OtherClass.Name; } else { tableName = "rel" + test.OtherClass.Name + test.OwnClass.Name; } ForeignKeyColumn fkColumn = rel.NewForeignKeyColumn(); fkColumn.Name = "ID" + test.OwnClass.Name; if (ri.OwnPoly) { rel.ForeignKeyTypeColumnName = "TC" + test.OwnClass.Name; } else { rel.ForeignKeyTypeColumnName = null; } rel.MappingTable = new NDO.Mapping.MappingTable(rel); rel.MappingTable.TableName = tableName; fkColumn = rel.MappingTable.NewForeignKeyColumn(); fkColumn.Name = "ID" + test.OtherClass.Name; if (ri.OtherPoly) { rel.MappingTable.ChildForeignKeyTypeColumnName = "TC" + test.OtherClass.Name; } else { rel.MappingTable.ChildForeignKeyTypeColumnName = null; } rel.MappingTable.ConnectionId = clMapping.ConnectionId; if (ri.OwnPoly) { ForeignKeyColumn dfkColumn = (ForeignKeyColumn)derivedRel.ForeignKeyColumns.FirstOrDefault(); dfkColumn.Name = ((ForeignKeyColumn)rel.ForeignKeyColumns.FirstOrDefault()).Name; derivedRel.ForeignKeyTypeColumnName = rel.ForeignKeyTypeColumnName; derivedRel.MappingTable = rel.MappingTable; } } }
/// <summary> /// Removes a relation from the Class object. /// </summary> /// <param name="r"></param> public void RemoveRelation(Relation r) { this.relations.Remove(r); this.Changed = true; }
/// <summary> /// Adds a default relation mapping. /// </summary> /// <param name="fieldName">Name of the field</param> /// <param name="referencedTypeName">Type name of the referenced class</param> /// <param name="isElement">True, if multiplicity is 1</param> /// <param name="relationName">Optional relation name</param> /// <param name="ownTypeIsPoly">True, if the class, containing the field, has a persistent base class</param> /// <param name="otherTypeIsPoly">True, if the related type has a persistent base class</param> /// <param name="mappingTableAttribute">If not null, the mapping information comes from this attribute.</param> /// <returns>A new constructed <code>Relation</code> object</returns> public Relation AddStandardRelation(string fieldName, string referencedTypeName, bool isElement, string relationName, bool ownTypeIsPoly, bool otherTypeIsPoly, MappingTableAttribute mappingTableAttribute) { // if (null != Parent) // Parent.this.Changed = true; Relation r = new Relation(this); r.FieldName = fieldName; r.ReferencedTypeName = referencedTypeName; //r.parent = this; r.RelationName = relationName; r.Multiplicity = isElement ? RelationMultiplicity.Element : RelationMultiplicity.List; int pos = referencedTypeName.LastIndexOf('.'); string refShortName = referencedTypeName.Substring(pos + 1); refShortName = refShortName.Replace("`", string.Empty); pos = this.FullName.LastIndexOf('.'); string myShortName = this.FullName.Substring(pos + 1); myShortName = myShortName.Replace("`", string.Empty); Relation foreignRelation = r.ForeignRelation; ForeignKeyColumn fkColumn = r.NewForeignKeyColumn(); // Element->x AND no MappingTable if (isElement && mappingTableAttribute == null && !(foreignRelation != null && foreignRelation.MappingTable != null)) { r.MappingTable = null; // Foreign Key is in the own table and points to rows of the other table fkColumn.Name = "ID" + refShortName; if (otherTypeIsPoly) { r.ForeignKeyTypeColumnName = "TC" + refShortName; } if (relationName != string.Empty) { fkColumn.Name += "_" + relationName; if (otherTypeIsPoly) { r.ForeignKeyTypeColumnName += "_" + relationName; } } } else // List or (Element with Mapping Table) { // These are the reasons for creating a mapping table: // 1. The MappingTableAttribute demands it // 2. We have a n:n relationship // 3. We have a 1:n relationship and the other type is poly // 4. The relation is bidirectional and the other side demands a mapping table bool needsMappingTable = mappingTableAttribute != null || null != foreignRelation && (foreignRelation.Multiplicity == RelationMultiplicity.List && r.Multiplicity == RelationMultiplicity.List) || otherTypeIsPoly && r.Multiplicity == RelationMultiplicity.List || null != foreignRelation && foreignRelation.MappingTable != null; // Foreign Key points to rows of our own table fkColumn.Name = "ID" + myShortName; if (ownTypeIsPoly && needsMappingTable) { r.ForeignKeyTypeColumnName = "TC" + myShortName; } else if (otherTypeIsPoly && !needsMappingTable) { r.ForeignKeyTypeColumnName = "TC" + refShortName; } if (relationName != string.Empty) { fkColumn.Name += "_" + relationName; if (ownTypeIsPoly) { r.ForeignKeyTypeColumnName += "_" + relationName; } } if (needsMappingTable) { r.AddMappingTable(refShortName, myShortName, otherTypeIsPoly, mappingTableAttribute); r.RemapForeignMappingTable(myShortName, refShortName, ownTypeIsPoly, otherTypeIsPoly, mappingTableAttribute); } else { r.MappingTable = null; } } this.relations.Add(r); return(r); }
public RelationFieldInfo(Relation rel, string tableName) { Rel = rel; TableName = tableName; }
private void GenerateMappingTable(NDO.Mapping.Class parentClass, NDO.Mapping.Class relClass, NDO.Mapping.Relation r, DataTable parentTable) { //MM 6 ggf. Tabelle anlegen // Gibt's die Table schon in dsSchema? // Nein: Anlegen DataTable dtMap = dsSchema.Tables[r.MappingTable.TableName]; if (null == dtMap) { dsSchema.Tables.Add(dtMap = new DataTable(r.MappingTable.TableName)); } //MM 7 ForeignKey-Spalten für eigene und Fremdklasse anlegen //MM 7 Wenn nötig auch die TypeColumns anlegen // Addiere die Spalte r.ForeignKeyColumnName, Typ der Spalte: parentClass.Oid.ColumnType bzw. int new ForeignKeyIterator(r).Iterate(delegate(ForeignKeyColumn fkColumn, bool isLastElement) { searchAndAddColumn(dtMap, fkColumn.Name, null, fkColumn.SystemType); }); // Lege ggf. die Typspalte an, Typ ist immer int if (r.ForeignKeyTypeColumnName != null) { searchAndAddColumn(dtMap, r.ForeignKeyTypeColumnName, null, typeof(int)); } new ForeignKeyIterator(r.MappingTable).Iterate(delegate(ForeignKeyColumn fkColumn, bool isLastElement) { searchAndAddColumn(dtMap, fkColumn.Name, null, fkColumn.SystemType); }); #if nix // Single oid column code // Addiere die Spalte r.MappingTable.ChildForeignKeyColumnName // Typ der Spalte muss ermittelt werden: // - Oid.FieldType // - [NDOObjectId] für Interfaces string typeName = null; Type defaultType = null; //TODO: Interfaces berücksichtigen if (relClass == null) // Interface { // Typ ist Interface throw new NotImplementedException("Interface"); } else { defaultType = relClass.Oid.FieldType; } #endif if (r.MappingTable.ChildForeignKeyTypeColumnName != null) { searchAndAddColumn(dtMap, r.MappingTable.ChildForeignKeyTypeColumnName, null, typeof(int)); } }
void IFieldInitializer.InitFields() { if (this.isInitialized) { return; // Avoid redundant calls, since InitFields is called in a recursive algorithm } this.isInitialized = true; Type oidTypeHint = this.OidTypeHint; FieldMap fieldMap = new FieldMap(Parent); Dictionary <string, MemberInfo> myPersistentFields = fieldMap.PersistentFields; List <string> relationsReady = new List <string>(); bool isDependent = ((OidColumn)oidColumns[0]).RelationName != null; foreach (OidColumn column in this.oidColumns) { if (isDependent && column.RelationName == null || !isDependent && column.RelationName != null) { throw new NDOException(113, "Wrong Oid mapping for type " + Parent.FullName + ". You can't mix OidColumns with and without a RelationName."); } } foreach (OidColumn column in this.oidColumns) { if (column.FieldName != null) { if (!myPersistentFields.ContainsKey(column.FieldName)) { throw new NDOException(20, "Can't find field " + Parent.FullName + "." + column.FieldName + '.'); } FieldInfo fi = (FieldInfo)myPersistentFields[column.FieldName]; column.SystemType = fi.FieldType; Field fieldMapping = Parent.FindField(fi.Name); if (fieldMapping == null) { throw new NDOException(7, "Can't find mapping information for field " + Parent.FullName + "." + fi.Name); } // This information will be deleted by the enhancer after generating the schema // to avoid redundant information in the mapping file. column.Name = fieldMapping.Column.Name; } else if (column.RelationName != null) { // Find and check the relation Relation r = Parent.FindRelation(column.RelationName); if (r == null || r.Multiplicity != RelationMultiplicity.Element || r.Composition) { throw new NDOException(109, "Wrong relation name " + column.RelationName + " in OidColumn definition of type " + Parent.FullName + '.' + " The RelationName must denote an existing assoziation with RelationMultiplicity.Element."); } bool found = false; foreach (string s in relationsReady) { if (column.RelationName == s) { found = true; break; } } if (!found) { relationsReady.Add(column.RelationName); // find all oid columns with the same RelationName List <OidColumn> allOidColumns = this.oidColumns.Where(oidc => oidc.RelationName == column.RelationName).ToList(); // find all FkColumns of the relation List <ForeignKeyColumn> fkColumns = r.ForeignKeyColumns.ToList(); // Both lists must have the same count if (allOidColumns.Count != fkColumns.Count) { throw new NDOException(110, "Count of Oid columns with relation name " + column.RelationName + " is different from count of foreign key columns of the named relation. Expected: " + fkColumns.Count + ". Count of OidColumns was: " + allOidColumns.Count + '.' + " Type = " + Parent.FullName + '.'); } // Now let's determine the oid types of the columns Class relClass = Parent.Parent.FindClass(r.ReferencedTypeName); // Resolve the Oid types of the related type. Endless recursion is not possible because of the test at the beginning of this method. if (allOidColumns.Count != relClass.Oid.OidColumns.Count()) { throw new NDOException(110, "Count of Oid columns with relation name " + column.RelationName + " is different from count of oid columns of the related type. Expected: " + fkColumns.Count + ". Count of OidColumns was: " + allOidColumns.Count + '.' + " Type = " + Parent.FullName + '.'); } ((IFieldInitializer)relClass).InitFields(); // Must initialize the system type and oid of the related class first. int i = 0; foreach (OidColumn relOidColumn in relClass.Oid.OidColumns) { // The column has the same type as the oid column of the related type ((OidColumn)allOidColumns[i]).SystemType = relOidColumn.SystemType; // The column has the same name as the foreign key column of the relation defined // by RelationName. // The enhancer will remove the name assigned here after generating the schema. ((OidColumn)allOidColumns[i]).Name = ((Column)fkColumns[i]).Name; i++; } } } else if (column.NetType != null) { column.SystemType = Type.GetType(column.NetType); if (column.SystemType == null) { throw new NDOException(11, "Type.GetType for the type name " + column.NetType + " failed; check your mapping File."); } } else if (oidTypeHint != null && this.oidColumns.Count == 1) { column.SystemType = oidTypeHint; } else // Default case if nothing is defined in the mapping or in NDOOidType { column.SystemType = typeof(Int32); if (this.oidColumns.Count == 1) { column.AutoIncremented = true; } } } if (!((IEnhancerSupport)Parent.Parent).IsEnhancing) { int autoIncCount = 0; foreach (OidColumn column in this.oidColumns) { // The size is only set for internal use by NDO. // Don't save this information in the mapping file. if (column.Size == 0) { column.Size = Parent.Parent.GetProvider(Parent).GetDefaultLength(column.SystemType); } if (column.AutoIncremented) { autoIncCount++; } } if (autoIncCount > 1) { throw new NDOException(112, "Type " + Parent.FullName + " has more than one autoincremented column. This is not supported by NDO. Check your mapping file or the OidColumn attributes in the source code."); } } }