public virtual void ToDataSet(ref DataSet dataSet)
        {
            // find corresponding datatable
            DataTable dataTable = dataSet.Tables[this.GetType().Name];

            if (dataTable == null)
            {
                dataTable = new DataTable(this.GetType().Name);
            }

            DataColumn dataColumn;
            DataRow    dataRow = dataTable.NewRow();

            foreach (FieldInfo field in this.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy))
            {
                foreach (Attribute attr in field.GetCustomAttributes(true))
                {
                    if (attr is ifcAttribute ifcAttr)
                    {
                        string          columnName   = field.Name.StartsWith("_") ? field.Name.Substring(1) : field.Name;
                        object          value        = SqliteAttributeOut(field, field.GetValue(this));
                        ifcSqlAttribute sqlAttribute = field.FieldType.GetCustomAttributes(true).FirstOrDefault(a => a is ifcSqlAttribute) as ifcSqlAttribute;
                        dataColumn = dataTable.Columns[columnName];
                        if (dataColumn == null)
                        {
                            dataColumn = new DataColumn(columnName, sqlAttribute == null ? typeof(string) : TypeFromTableId(sqlAttribute.SqlTableId));
                            dataTable.Columns.Add(dataColumn);
                            dataColumn.AllowDBNull = ifcAttr.optional;
                        }
                        dataRow.SetField(dataColumn, value);
                    }
                }
            }

            dataColumn = dataTable.Columns["Id"];
            if (dataColumn == null)
            {
                dataColumn = new DataColumn("Id", typeof(int));
                dataTable.Columns.Add(dataColumn);
            }
            dataRow.SetField(dataColumn, this.LocalId);

            // before we add the row, we sort the values by their ordinal position
            foreach (FieldInfo field in this.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy))
            {
                foreach (Attribute attr in field.GetCustomAttributes(true))
                {
                    if (attr is ifcAttribute ifcAttr)
                    {
                        string columnName = field.Name.StartsWith("_") ? field.Name.Substring(1) : field.Name;
                        dataColumn = dataTable.Columns[columnName];
                        dataColumn.SetOrdinal(ifcAttr.OrdinalPosition);
                    }
                }
            }

            dataTable.Rows.Add(dataRow);
            if (dataSet.Tables[dataTable.TableName] == null)
            {
                dataSet.Tables.Add(dataTable);
            }
        }
        public virtual void ToSqliteDataSet(ref SQLiteDataSet dataSet, bool updateExisting, int prevEntityId)
        {
            string paramName = "";

            // find corresponding datatable
            bool            addNewTable = false;
            SQLiteDataTable dataTable   = dataSet.Tables.FirstOrDefault(t => t.Name == this.GetType().Name);

            if (dataTable == null)
            {
                addNewTable = true;
                dataTable   = new SQLiteDataTable(this.GetType().Name);
            }

            // find corresponding datarow
            bool          addNewRow = false;
            SQLiteDataRow dataRow   = dataTable.Rows.FirstOrDefault(r => r.Id == this.LocalId || r.IsEmpty);

            if (dataRow == null)
            {
                addNewRow = true;
                dataRow   = new SQLiteDataRow();
            }
            else
            {
                SQLiteDataField idField = dataRow.Fields.FirstOrDefault(f => f.Parameter.ParameterName == "Id");
                if (idField != null)
                {
                    idField.Parameter.Value = this.LocalId;
                }
            }

            if (addNewRow == true || updateExisting == true)
            {
                if (this is CartesianPoint || this is Direction)
                {
                    double X = 0;
                    double Y = 0;
                    double?Z = null;
                    if (this is CartesianPoint cp)
                    {
                        if (cp.Coordinates.Count > 1)
                        {
                            X = (double)cp.Coordinates[0]; Y = (double)cp.Coordinates[1];
                        }
                        if (cp.Coordinates.Count > 2)
                        {
                            Z = (double)cp.Coordinates[2];
                        }
                    }
                    else if (this is Direction dir)
                    {
                        if (dir.DirectionRatios.Count > 1)
                        {
                            X = (double)dir.DirectionRatios[0]; Y = (double)dir.DirectionRatios[1];
                        }
                        if (dir.DirectionRatios.Count > 2)
                        {
                            Z = (double)dir.DirectionRatios[2];
                        }
                    }
                    dataRow.Fields.Add(new SQLiteDataField(1, "X", DbType.Double, false, X));
                    dataRow.Fields.Add(new SQLiteDataField(2, "Y", DbType.Double, false, Y));
                    dataRow.Fields.Add(new SQLiteDataField(3, "Z", DbType.Double, true, Z));
                }
                else if (this is EntityComment ec)
                {
                    dataRow.Fields.Add(new SQLiteDataField(1, "Comment", DbType.String, true, ec.CommentLine));
                    dataRow.Fields.Add(new SQLiteDataField(2, "PreviousEntity", DbType.Int32, false, prevEntityId));
                }
                else
                {
                    foreach (FieldInfo field in this.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy))
                    {
                        IEnumerable <ifcAttribute> ifcAttributes = field.GetCustomAttributes(true).Where(a => a is ifcAttribute).Cast <ifcAttribute>();
                        foreach (ifcAttribute attr in ifcAttributes)
                        {
                            object[] fieldAttributes = null;
                            if (field.FieldType.IsGenericType && field.FieldType.GetGenericArguments()[0].IsEnum && field.FieldType.GetGenericTypeDefinition() == typeof(Nullable <>))
                            {
                                fieldAttributes = field.FieldType.GetGenericArguments()[0].GetCustomAttributes(true);
                            }
                            else
                            {
                                fieldAttributes = field.FieldType.GetCustomAttributes(true);
                            }

                            ifcSqlAttribute sqlAttribute = fieldAttributes.FirstOrDefault(a => a is ifcSqlAttribute) as ifcSqlAttribute;
                            // each attribute is represented as SQLiteDataField
                            paramName = field.Name.StartsWith("_") ? field.Name.Substring(1) : field.Name;
                            if (sqlAttribute != null)
                            {
                                SQLiteDataField sqliteField = dataRow.Fields.FirstOrDefault(f => f.Parameter.ParameterName == paramName);
                                if (sqliteField == null)
                                {
                                    sqliteField = new SQLiteDataField(attr.OrdinalPosition, paramName, DbTypeFromTableId(sqlAttribute.SqlTableId), attr.optional || attr.derived, SqliteAttributeOut(field, field.GetValue(this)));
                                    dataRow.Fields.Add(sqliteField);
                                }
                                else
                                {
                                    sqliteField.Parameter.Value = SqliteAttributeOut(field, field.GetValue(this));
                                }
                            }
                        }
                    }
                }
            }

            if (addNewRow)
            {
                if (dataRow.Fields.Count > 0)
                {
                    dataRow.Fields.Add(new SQLiteDataField(0, "Id", DbType.Int32, false, this.LocalId));
                    dataRow.Fields.Add(new SQLiteDataField(dataRow.Fields.Count, "EndOfLineComment", DbType.String, true, this.EndOfLineComment));
                }

                // before we add the row, we sort the values by their ordinal position
                dataRow.OrderValuesByOrdinalPosition();
                dataTable.Rows.Add(dataRow);
                if (addNewTable)
                {
                    dataSet.Tables.Add(dataTable);
                }
            }
        }