    QString QxClassX::dumpSqlSchema()
    {
       qDebug("[QxOrm] qx::QxClassX::dumpSqlSchema() : %s", "be careful with this function, it's just an example and tested only with SQLite database, so it's strongly recommended to write your own function to create your SQL schema");
       QxCollection<QString, IxClass *> * pAllClasses = QxClassX::getAllClasses();
       if (! pAllClasses) { qAssert(false); return ""; }
       QString sql; long lSqlCount = 0;

       for (long k = 0; k < pAllClasses->count(); k++)
       {
          IxClass * pClass = pAllClasses->getByIndex(k);
          if (! pClass) { continue; }

          // If the class is a parameter or a service from 'QxService' module, it's not a persistent class
          if (pClass->isKindOf("qx::service::IxParameter") || pClass->isKindOf("qx::service::IxService")) { continue; }

          // ----
          // Here, you can filter other classes using property bag (meta-data), for example :
          //    QString sProp = pClass->getPropertyBag("NOT_A_DATABASE_OBJECT").toString();
          //    if (sProp == "1") { continue; }
          // ----

          // Get the version of the class : if (version = 0) then 'CREATE TABLE', else if (version > 0) then 'ALTER TABLE'
          long lVersion = pClass->getVersion();
          bool bCreateTable = (lVersion <= 0);
          sql += (bCreateTable ? "CREATE TABLE " : "ALTER TABLE ");
          sql += pClass->getName() + " ";
          sql += (bCreateTable ? "(" : "ADD (");

          // Get the primary key (id) of table, all columns into table, and other parameters associated to table
          IxDataMember * pId = pClass->getId();
          IxDataMemberX * pDataMemberX = pClass->getDataMemberX();
          QxSoftDelete oSoftDelete = pClass->getSoftDelete();

          // Insert primary key (id) to SQL schema
          if (pId && (bCreateTable || (pId->getVersion() >= lVersion)))
          { sql += pId->getSqlNameAndTypeAndParams(", ") + ", "; qAssert(! pId->getSqlType().isEmpty()); }

          // Insert all columns to SQL schema
          for (long l = 0; (pDataMemberX && (l < pDataMemberX->count_WithDaoStrategy())); l++)
          {
             IxDataMember * p = pDataMemberX->get_WithDaoStrategy(l);
             if (isValid_DataMember(p) && (p != pId) && (bCreateTable || (p->getVersion() >= lVersion)))
             { sql += p->getSqlNameAndTypeAndParams(", ") + ", "; qAssert(! p->getSqlType().isEmpty()); }

             // ----
             // Here, you can use property bag (meta-data) to add some SQL features, for example :
             //    QString sProp = p->getPropertyBag("INDEX").toString();
             //    if (sProp == "1") { sql += "CREATE INDEX" + etc...; }
             // ----
          }

          // Insert soft delete behaviour to SQL schema
          if (bCreateTable && ! oSoftDelete.isEmpty())
          { sql += oSoftDelete.buildSqlQueryToCreateTable() + ", "; }

          // Insert all relations to SQL schema
          for (long l = 0; (pDataMemberX && (l < pDataMemberX->count_WithDaoStrategy())); l++)
          {
             IxDataMember * p = pDataMemberX->get_WithDaoStrategy(l);
             QxSqlRelationParams params(0, 0, (& sql), NULL, NULL, NULL);
             if (isValid_SqlRelation(p) && (p != pId) && (bCreateTable || (p->getVersion() >= lVersion)))
             { p->getSqlRelation()->createTable(params); }
          }

          // Terminate SQL schema for current class
          sql = sql.left(sql.count() - 2); // Remove last ", "
          sql += ")\n";
          lSqlCount++;

          // Create extra-table from relations (for example, many-to-many relation needs an extra-table)
          for (long l = 0; (pDataMemberX && (l < pDataMemberX->count_WithDaoStrategy())); l++)
          {
             IxDataMember * p = pDataMemberX->get_WithDaoStrategy(l);
             if (isValid_SqlRelation(p) && (p != pId) && (bCreateTable || (p->getVersion() >= lVersion)))
             {
                QString sqlExtraTable = p->getSqlRelation()->createExtraTable();
                if (sqlExtraTable.isEmpty()) { continue; }
                sql += sqlExtraTable + "\n";
             }
          }
       }

       qDebug("[QxOrm] start dump SQL schema (%ld)", lSqlCount);
       qDebug("%s", qPrintable(sql));
       qDebug("[QxOrm] %s", "end dump SQL schema");

       return sql;
    }

    bool QxClassX::isValid_DataMember(IxDataMember * p)
    {
       return (p && p->getDao() && ! p->hasSqlRelation());
    }

    bool QxClassX::isValid_SqlRelation(IxDataMember * p)
    {
       bool bIsValid = (p && p->getDao() && p->hasSqlRelation());
       if (bIsValid) { p->getSqlRelation()->init(); }
       return bIsValid;
    }