コード例 #1
0
 /// <summary>
 /// Construct a new MappingTable
 /// </summary>
 public MappingTable(Relation parent)
     : base(parent)
 {
 }
コード例 #2
0
ファイル: SchemaGenerator.cs プロジェクト: mirkomaty/NDO
        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));
            }
        }
コード例 #3
0
ファイル: Class.cs プロジェクト: mirkomaty/NDO
 /// <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;
 }
コード例 #4
0
ファイル: MappingGenerator.cs プロジェクト: mirkomaty/NDO
        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;
                }
            }
        }
コード例 #5
0
ファイル: Class.cs プロジェクト: mirkomaty/NDO
 /// <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;
 }
コード例 #6
0
ファイル: Class.cs プロジェクト: mirkomaty/NDO
        /// <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);
        }
コード例 #7
0
ファイル: RelationFieldInfo.cs プロジェクト: mirkomaty/NDO
 public RelationFieldInfo(Relation rel, string tableName)
 {
     Rel       = rel;
     TableName = tableName;
 }
コード例 #8
0
ファイル: SchemaGenerator.cs プロジェクト: mirkomaty/NDO
        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));
            }
        }
コード例 #9
0
        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.");
                }
            }
        }