private void InsertRow(string tableName, SQLiteDataRow row)
        {
            List <string> valueNames        = row.Fields.Select(p => p.Parameter.ParameterName).ToList();
            List <string> valuePlaceholders = row.Fields.Select(p => "@" + p.Parameter.ParameterName).ToList();
            List <object> values            = row.Fields.Select(p => p.Parameter.Value).ToList();

            // we dont insert when: no ValueNames are given _OR_ all Values are "NULL"
            if (valueNames.Count <= 0 || values.All(item => item == null))
            {
                return;
            }
            string commandText = string.Format("INSERT INTO {0} ({1}) VALUES ({2})", tableName, string.Join(",", valueNames), string.Join(",", valuePlaceholders));

            try
            {
                SQLiteCommand command = new SQLiteCommand(commandText, this.Connection);
                for (int i = 0; i < values.Count; i++)
                {
                    command.Parameters.AddWithValue(valuePlaceholders[i], values[i]);
                }
                int retVal = command.ExecuteNonQuery();
            }


            catch (SQLiteException sqliteExc)
            {
                string msg = string.Format("Error on 'INSERT INTO {0}': {1}", tableName, sqliteExc.Message.Split('\n')[1]);
                Console.WriteLine(msg);
                Debug.WriteLine(msg);
            }
            catch (Exception e)
            {
                string msg = string.Format("Exception in executing command: '{0}':\n{1}", commandText, e.Message);
                Debug.WriteLine(msg);
            }
        }
        private bool BuildIfcDataSet(ref SQLiteDataSet ifcDataSet)
        {
            if (ifcDataSet == null)
            {
                return(false);
            }

            SQLiteDataField sqliteField;
            string          paramName;

            foreach (Type t in Assembly.GetAssembly(typeof(ifc.ENTITY)).GetTypes())
            {
                if (t.IsClass)
                {
                    if (!t.IsAbstract)
                    {
                        if (t.IsSubclassOf(typeof(ifc.ENTITY)))
                        {
                            SQLiteDataTable dataTable = new SQLiteDataTable(t.Name);
                            SQLiteDataRow   dataRow   = new SQLiteDataRow();
                            foreach (FieldInfo field in t.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy))
                            {
                                foreach (Attribute attr in field.GetCustomAttributes(true))
                                {
                                    if (attr is ifcAttribute ifcAttribute)
                                    {
                                        object[] fieldAttributes = null;
                                        if ((field.FieldType.IsGenericType) && (field.FieldType.GetGenericTypeDefinition() == typeof(Nullable <>)) && (field.FieldType.GetGenericArguments()[0].IsEnum))
                                        {
                                            fieldAttributes = field.FieldType.GetGenericArguments()[0].GetCustomAttributes(true);
                                        }
                                        else
                                        {
                                            fieldAttributes = field.FieldType.GetCustomAttributes(true);
                                        }
                                        if (null != fieldAttributes)
                                        {
                                            foreach (Attribute attr2 in fieldAttributes)
                                            {
                                                if (attr2 is ifc.ifcSqlAttribute sqlAttribute)
                                                {
                                                    paramName   = field.Name.StartsWith("_") ? field.Name.Substring(1) : field.Name;
                                                    sqliteField = new SQLiteDataField(ifcAttribute.OrdinalPosition, paramName, ENTITY.DbTypeFromTableId(sqlAttribute.SqlTableId));
                                                    sqliteField.Parameter.IsNullable = ifcAttribute.optional || ifcAttribute.derived;
                                                    dataRow.Fields.Add(sqliteField);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            dataRow.Fields.Add(new SQLiteDataField(0, "Id", DbType.Int32));
                            dataRow.Fields.Add(new SQLiteDataField(dataRow.Fields.Count, "EndOfLineComment", DbType.String));

                            // before we add the row, we sort the values by their ordinal position
                            dataRow.OrderValuesByOrdinalPosition();

                            dataTable.Rows.Add(dataRow);
                            ifcDataSet.Tables.Add(dataTable);
                        }
                    }
                }
            }
            return(true);
        }
        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);
                }
            }
        }