Can QxOrm persist pointers to abstract classes?

Forum for posting problems using QxOrm library

Can QxOrm persist pointers to abstract classes?

Postby achrislong » Wed Jul 11, 2012 6:20 pm

[I asked this on StackOverflow, but thought I'd ask here too since I haven't yet gotten a definitive answer.]

I am trying to figure out how to use QxOrm to persist a large, complex class structure. I've made some progress, but am stuck on what to do with pointers to abstract classes.

Here's a simple example, where Table (a concrete class) has a pointer to some kind of Shape (an abstract class):

Code: Select all
class Table {
    Shape* top;
};

class Shape {
public:
    virtual float getWidth() = 0;
};

class Square : public Shape {
    virtual float getWidth();
};

class Circle : public Shape {
    virtual float getWidth();
};


I get error messages complaining that Shape is abstract when I try this.

It looks to me like this is impossible to do with QxOrm, I suspect because its only inheritance model is Concrete.

Does anyone know if this is possible or not? I'd rather not give up on QxOrm since it looks good in many ways (and I've put a bunch of time into it already), but it looks like I will have to.

I know about QX_REGISTER_ABSTRACT_CLASS. It does not help for this use case.

I experimented with making the comment class in the qxBlog example abstract. I made it subclass qx::IxPersistable and used the QX_REGISTER_ABSTRACT_CLASS macro. When I compile, it dies in the invocation of the macro QX_PERSISTABLE_CPP, with:

../../../QxOrm/include/QxDao/../../inl/QxDao/QxDao_Count.inl:36: error: cannot declare variable 't' to be of abstract type 'comment'

There are similar error messages from other places, too.

Thanks!
achrislong
 
Posts: 4
Joined: Wed Jul 11, 2012 6:09 pm

Re: Can QxOrm persist pointers to abstract classes?

Postby QxOrm admin » Wed Jul 11, 2012 7:34 pm

Hi,

I experimented with making the comment class in the qxBlog example abstract. I made it subclass qx::IxPersistable and used the QX_REGISTER_ABSTRACT_CLASS macro. When I compile, it dies in the invocation of the macro QX_PERSISTABLE_CPP, with:
../../../QxOrm/include/QxDao/../../inl/QxDao/QxDao_Count.inl:36: error: cannot declare variable 't' to be of abstract type 'comment'

Using qx::IxPersistable interface (http://www.qxorm.com/qxorm_en/faq.html#faq_260) and an abstract class, you don't have to write QX_PERSISTABLE_HPP and QX_PERSISTABLE_CPP macros : it doesn't make sense (those macros must be used only with concretes types).
qx::IxPersistable interface provides a way to persist an instance without knowing its real type (so typically using a base class pointer).
QX_PERSISTABLE_HPP and QX_PERSISTABLE_CPP macros are used to implement all persistables methods (qxFetch, qxSave, etc...).
Since a C++ abstract class cannot have a table associated into the database (because the class cannot be instantiated), you can't implement persistables methods.
So here is the idea if I use your example :
Code: Select all
    class Table : public qx::IxPersistable {
        QX_PERSISTABLE_HPP(Table)
        Shape* top;
    };

    class Shape : public qx::IxPersistable {
        // Don't use QX_PERSISTABLE_HPP macro in the abstract class !!!
    public:
        virtual float getWidth() = 0;
    };

    class Square : public Shape {
        QX_PERSISTABLE_HPP(Square)
        virtual float getWidth();
    };

    class Circle : public Shape {
        QX_PERSISTABLE_HPP(Circle)
        virtual float getWidth();
    };


Now your problem : you have a persistent class named Table. This class contains a pointer to a persistent base class named Shape.
And when you save an instance of Table, if Shape is a Square, then save it to the Square table, else if Shape is a Circle, then save it to the Circle table, etc...
Don't forget that there is a database associated with your C++ code.
What is your database schema in this case ?

In your Table table, you need an extra-information to manage you base class pointer : the real type associated to the pointer.
QxOrm library will not manage automatically this extra-information, but I think that you could try something like this using QxOrm triggers (http://www.qxorm.com/qxorm_en/faq.html#faq_130) and C++ dynamic_cast function :
1- to store a Shape, your Table table must have a column to store the ID Shape + another column to store the real type of Shape ;
2- then create some triggers, for example :
Code: Select all
void onAfterFetch(Table * t, qx::dao::detail::IxDao_Helper * dao)
{
   if (t->myShapeType == "Square") { t->top = new Square(); }
   else if (t->myShapeType == "Circle") { t->top = new Circle(); }
   else if (etc...) { etc... }

   if ((t->top != NULL) && (t->myShapeID > 0))
   {
      t->top->setId(t->myShapeID);
      QSqlError daoErr = t->top->qxFetchById();
   }
}

void onBeforeUpdate(Table * t, qx::dao::detail::IxDao_Helper * dao)
{
   if (dynamic_cast<Square *>(t->top) != NULL) { t->myShapeType = "Square";  }
   else if (dynamic_cast<Circle *>(t->top) != NULL) { t->myShapeType = "Circle";  }
   else if (etc...) { etc... }

   if (t->top)
   {
      t->myShapeID = t->top->getId();
      QSqlError daoErr = t->top->qxSave();
   }
}

// etc...
QxOrm admin
 

Re: Can QxOrm persist pointers to abstract classes?

Postby achrislong » Thu Jul 12, 2012 7:24 pm

Thanks for the help. Unfortunately, I am now running into problems because when it generates a query for
Code: Select all
qx::dao::fetch_by_id_with_all_relation
, the query includes references to the table for the abstract class (which doesn't exist) and I get a "Parameter count mismatch" error.

I see now that I'm going to have to track all the concrete descendants and their tables and do queries on those any time I want a query on all the Shapes. I'm not sure how to hook into the QxOrm machinery to make that happen, though.

I guess I can't blame QxOrm for this since it appears no other framework does any better (and many do worse), but it is disappointing how much work it takes to persist what is from the object-oriented perspective such a simple and common idiom.
achrislong
 
Posts: 4
Joined: Wed Jul 11, 2012 6:09 pm

Re: Can QxOrm persist pointers to abstract classes?

Postby QxOrm admin » Thu Jul 12, 2012 7:37 pm

I guess I can't blame QxOrm for this since it appears no other framework does any better (and many do worse), but it is disappointing how much work it takes to persist what is from the object-oriented perspective such a simple and common idiom.

You're right, and it's not an easy task.
boost::serialization implements this idiom very well, and you can serialize/deserialize without any problem an instance with pointers to base classes.
So maybe you could have a different approach, since QxOrm library works with boost::serialization.
You could for example imagine that you have a table with only 2 columns to store this kind of objects :
* 1 column to store an ID ;
* 1 column to store a binary or XML structure that contains your instance serialized.

I don't know if it's a good idea or not, but maybe you could test it...
QxOrm admin
 

Re: Can QxOrm persist pointers to abstract classes?

Postby QxOrm admin » Fri Jul 13, 2012 9:21 am

To come back to my first answer using qx::IxPersistable and triggers : I think I have a generic solution to not have to deal with all derived classes !
I made some tests, it seems to work well.
Here is the source code, if you have some questions about it... (the only thing is that MyBaseClass cannot be abstract, I don't know why yet).

MyBaseClass.h file :
Code: Select all
// ----------------------------------
// MyBaseClass.h

class QX_DLL2_EXPORT MyBaseClass : public qx::IxPersistable
{

   QX_PERSISTABLE_HPP(MyBaseClass)

public:

   long id;

   MyBaseClass() : qx::IxPersistable(), id(0) { ; }
   virtual ~MyBaseClass() { ; }

};

QX_REGISTER_HPP_QX_DLL2(MyBaseClass, qx::trait::no_base_class_defined, 0)

typedef boost::shared_ptr<MyBaseClass> MyBaseClass_ptr;


MyDerivedClass1.h file :
Code: Select all
// ----------------------------------
// MyDerivedClass1.h

class QX_DLL2_EXPORT MyDerivedClass1 : public MyBaseClass
{

   QX_PERSISTABLE_HPP(MyDerivedClass1)

public:

   QString description;

   MyDerivedClass1() : MyBaseClass() { ; }
   virtual ~MyDerivedClass1() { ; }

};

QX_REGISTER_HPP_QX_DLL2(MyDerivedClass1, MyBaseClass, 0)

typedef boost::shared_ptr<MyDerivedClass1> MyDerivedClass1_ptr;


MyDerivedClass2.h file :
Code: Select all
// ----------------------------------
// MyDerivedClass2.h

class QX_DLL2_EXPORT MyDerivedClass2 : public MyBaseClass
{

   QX_PERSISTABLE_HPP(MyDerivedClass2)

public:

   QString prop1;
   QString prop2;

   MyDerivedClass2() : MyBaseClass() { ; }
   virtual ~MyDerivedClass2() { ; }

};

QX_REGISTER_HPP_QX_DLL2(MyDerivedClass2, MyBaseClass, 0)

typedef boost::shared_ptr<MyDerivedClass2> MyDerivedClass2_ptr;


MyContainer.h file :
Code: Select all
// ----------------------------------
// MyContainer.h

class QX_DLL2_EXPORT MyContainer
{

public:

   long id;

   long base_id;
   QString base_type;
   MyBaseClass_ptr base_ptr;

   MyContainer() : id(0), base_id(0) { ; }
   virtual ~MyContainer() { ; }

   void onBeforeInsert(qx::dao::detail::IxDao_Helper * dao);
   void onBeforeUpdate(qx::dao::detail::IxDao_Helper * dao);
   void onBeforeDelete(qx::dao::detail::IxDao_Helper * dao);
   void onBeforeFetch(qx::dao::detail::IxDao_Helper * dao);
   void onAfterInsert(qx::dao::detail::IxDao_Helper * dao);
   void onAfterUpdate(qx::dao::detail::IxDao_Helper * dao);
   void onAfterDelete(qx::dao::detail::IxDao_Helper * dao);
   void onAfterFetch(qx::dao::detail::IxDao_Helper * dao);

   void insertOrUpdateBasePtr(qx::dao::detail::IxDao_Helper * dao);

};

QX_REGISTER_HPP_QX_DLL2(MyContainer, qx::trait::no_base_class_defined, 0)

typedef boost::shared_ptr<MyContainer> MyContainer_ptr;

namespace qx {
namespace dao {
namespace detail {

template <>
struct QxDao_Trigger<MyContainer>
{

   static inline void onBeforeInsert(MyContainer * t, qx::dao::detail::IxDao_Helper * dao)   { if (t) { t->onBeforeInsert(dao); } }
   static inline void onBeforeUpdate(MyContainer * t, qx::dao::detail::IxDao_Helper * dao)   { if (t) { t->onBeforeUpdate(dao); } }
   static inline void onBeforeDelete(MyContainer * t, qx::dao::detail::IxDao_Helper * dao)   { if (t) { t->onBeforeDelete(dao); } }
   static inline void onBeforeFetch(MyContainer * t, qx::dao::detail::IxDao_Helper * dao)    { if (t) { t->onBeforeFetch(dao); } }
   static inline void onAfterInsert(MyContainer * t, qx::dao::detail::IxDao_Helper * dao)    { if (t) { t->onAfterInsert(dao); } }
   static inline void onAfterUpdate(MyContainer * t, qx::dao::detail::IxDao_Helper * dao)    { if (t) { t->onAfterUpdate(dao); } }
   static inline void onAfterDelete(MyContainer * t, qx::dao::detail::IxDao_Helper * dao)    { if (t) { t->onAfterDelete(dao); } }
   static inline void onAfterFetch(MyContainer * t, qx::dao::detail::IxDao_Helper * dao)     { if (t) { t->onAfterFetch(dao); } }

};

} // namespace detail
} // namespace dao
} // namespace qx


MyBaseClass.cpp file :
Code: Select all
// ----------------------------------
// MyBaseClass.cpp

QX_REGISTER_CPP_QX_DLL2(MyBaseClass)
QX_PERSISTABLE_CPP(MyBaseClass)

namespace qx {
template <> void register_class(QxClass<MyBaseClass> & t)
{
   t.id(& MyBaseClass::id, "id");
}}


MyDerivedClass1.cpp file :
Code: Select all
// ----------------------------------
// MyDerivedClass1.cpp

QX_REGISTER_CPP_QX_DLL2(MyDerivedClass1)
QX_PERSISTABLE_CPP(MyDerivedClass1)

namespace qx {
template <> void register_class(QxClass<MyDerivedClass1> & t)
{
   t.data(& MyDerivedClass1::description, "description");
}}


MyDerivedClass2.cpp file :
Code: Select all
// ----------------------------------
// MyDerivedClass2.cpp

QX_REGISTER_CPP_QX_DLL2(MyDerivedClass2)
QX_PERSISTABLE_CPP(MyDerivedClass2)

namespace qx {
template <> void register_class(QxClass<MyDerivedClass2> & t)
{
   t.data(& MyDerivedClass2::prop1, "prop1");
   t.data(& MyDerivedClass2::prop2, "prop2");
}}


MyContainer.cpp file :
Code: Select all
// ----------------------------------
// MyContainer.cpp

QX_REGISTER_CPP_QX_DLL2(MyContainer)

namespace qx {
template <> void register_class(QxClass<MyContainer> & t)
{
   qx::IxDataMember * pData = NULL;

   pData = t.id(& MyContainer::id, "id");
   pData = t.data(& MyContainer::base_id, "base_id");
   pData = t.data(& MyContainer::base_type, "base_type");

   pData = t.data(& MyContainer::base_ptr, "base_ptr");
   pData->setDao(false); // Not a part of the table
}}

void MyContainer::onBeforeInsert(qx::dao::detail::IxDao_Helper * dao)
{
   if (! dao) { qAssert(false); return; }
   if (dao->error().isValid()) { return; }
   if (! base_ptr || ! base_ptr->qxClass()) { return; }

   base_id = base_ptr->id;
   base_type = base_ptr->qxClass()->getKey();
}

void MyContainer::onBeforeUpdate(qx::dao::detail::IxDao_Helper * dao)
{
   if (! dao) { qAssert(false); return; }
   if (dao->error().isValid()) { return; }
   if (! base_ptr || ! base_ptr->qxClass()) { return; }

   base_id = base_ptr->id;
   base_type = base_ptr->qxClass()->getKey();
}

void MyContainer::onBeforeDelete(qx::dao::detail::IxDao_Helper * dao)
{
   if (! dao) { qAssert(false); return; }
   if (dao->error().isValid()) { return; }
   // Nothing to do here !
}

void MyContainer::onBeforeFetch(qx::dao::detail::IxDao_Helper * dao)
{
   if (! dao) { qAssert(false); return; }
   if (dao->error().isValid()) { return; }
   // Nothing to do here !
}

void MyContainer::onAfterInsert(qx::dao::detail::IxDao_Helper * dao)
{
   if (! dao) { qAssert(false); return; }
   if (dao->error().isValid()) { return; }
   insertOrUpdateBasePtr(dao);
}

void MyContainer::onAfterUpdate(qx::dao::detail::IxDao_Helper * dao)
{
   if (! dao) { qAssert(false); return; }
   if (dao->error().isValid()) { return; }
   insertOrUpdateBasePtr(dao);
}

void MyContainer::onAfterDelete(qx::dao::detail::IxDao_Helper * dao)
{
   if (! dao) { qAssert(false); return; }
   if (dao->error().isValid()) { return; }

   if (base_ptr)
   {
      QVariant idEmpty;
      QSqlError daoError = base_ptr->qxDeleteById(idEmpty, (& dao->database()));
      dao->updateError(daoError);
   }
}

void MyContainer::onAfterFetch(qx::dao::detail::IxDao_Helper * dao)
{
   if (! dao) { qAssert(false); return; }
   if (dao->error().isValid()) { return; }

   if ((base_id > 0) && (! base_type.isEmpty()))
   {
      MyBaseClass * pBase = qx::create_nude_ptr<MyBaseClass>(base_type);
      if (! pBase) { qAssert(false); return; }
      base_ptr.reset(pBase);
      QVariant vId = base_id; QStringList lstEmpty;
      QSqlError daoError = base_ptr->qxFetchById(vId, lstEmpty, lstEmpty, (& dao->database()));
      dao->updateError(daoError);
   }
}

void MyContainer::insertOrUpdateBasePtr(qx::dao::detail::IxDao_Helper * dao)
{
   static bool bInEvent = false;
   if (! base_ptr || bInEvent) { return; }
   bInEvent = true;

   QStringList lstEmpty; QVariant idEmpty;
   QSqlError daoError; qx::QxSqlQuery queryEmpty;
   qx_bool bExist = base_ptr->qxExist(idEmpty, (& dao->database()));
   if (bExist)
   {
      daoError = base_ptr->qxUpdate(queryEmpty, lstEmpty, lstEmpty, (& dao->database()));
      dao->updateError(daoError);
   }
   else
   {
      daoError = base_ptr->qxInsert(lstEmpty, (& dao->database()));
      if (! daoError.isValid()) { daoError = qx::dao::update((* this), (& dao->database()), QStringList() << "base_id" << "base_type"); }
      dao->updateError(daoError);
   }

   bInEvent = false;
}


main.cpp file to do some tests :
Code: Select all
   daoError = qx::dao::create_table<MyDerivedClass1>(); qAssert(! daoError.isValid());
   daoError = qx::dao::create_table<MyDerivedClass2>(); qAssert(! daoError.isValid());
   daoError = qx::dao::create_table<MyContainer>(); qAssert(! daoError.isValid());

   MyContainer b1;
   MyDerivedClass1_ptr pD1 = MyDerivedClass1_ptr(new MyDerivedClass1());
   pD1->description = "my desc";
   b1.base_ptr = pD1;
   daoError = qx::dao::insert(b1); qAssert(! daoError.isValid());

   MyContainer b2;
   MyDerivedClass2_ptr pD2 = MyDerivedClass2_ptr(new MyDerivedClass2());
   pD2->prop1 = "my prop1";
   pD2->prop2 = "my prop2";
   b2.base_ptr = pD2;
   daoError = qx::dao::insert(b2); qAssert(! daoError.isValid());

   MyContainer b3;
   b3.base_ptr = pD1;
   pD1->description = "my desc modified";
   daoError = qx::dao::insert(b3); qAssert(! daoError.isValid());

   QList<MyContainer_ptr> all;
   daoError = qx::dao::fetch_all(all);
   qx::dump(all);


And all output traces :
Code: Select all
[QxOrm] sql query (0 ms) : CREATE TABLE MyDerivedClass1 (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, description TEXT)
[QxOrm] sql query (0 ms) : CREATE TABLE MyDerivedClass2 (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, prop1 TEXT, prop2 TEXT)
[QxOrm] sql query (16 ms) : CREATE TABLE MyContainer (id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, base_id INTEGER, base_type TEXT)
[QxOrm] sql query (0 ms) : SELECT MyDerivedClass1.id AS MyDerivedClass1_id_0 FROM MyDerivedClass1 WHERE MyDerivedClass1.id = :id
[QxOrm] sql query (0 ms) : INSERT INTO MyDerivedClass1 (description) VALUES (:description)
[QxOrm] sql query (0 ms) : UPDATE MyContainer SET id = :id, base_id = :base_id, base_type = :base_type WHERE id = :id_bis
[QxOrm] sql query (3245 ms) : INSERT INTO MyContainer (base_id, base_type) VALUES (:base_id, :base_type)
[QxOrm] sql query (0 ms) : SELECT MyDerivedClass2.id AS MyDerivedClass2_id_0 FROM MyDerivedClass2 WHERE MyDerivedClass2.id = :id
[QxOrm] sql query (0 ms) : INSERT INTO MyDerivedClass2 (prop1, prop2) VALUES (:prop1, :prop2)
[QxOrm] sql query (0 ms) : UPDATE MyContainer SET id = :id, base_id = :base_id, base_type = :base_type WHERE id = :id_bis
[QxOrm] sql query (0 ms) : INSERT INTO MyContainer (base_id, base_type) VALUES (:base_id, :base_type)
[QxOrm] sql query (0 ms) : SELECT MyDerivedClass1.id AS MyDerivedClass1_id_0 FROM MyDerivedClass1 WHERE MyDerivedClass1.id = :id
[QxOrm] sql query (0 ms) : UPDATE MyDerivedClass1 SET id = :id, description = :description WHERE id = :id_bis
[QxOrm] sql query (15 ms) : INSERT INTO MyContainer (base_id, base_type) VALUES (:base_id, :base_type)
[QxOrm] sql query (0 ms) : SELECT MyDerivedClass1.id AS MyDerivedClass1_id_0, MyDerivedClass1.description AS MyDerivedClass1_description_0 FROM MyDerivedClass1 WHERE MyDerivedClass1.id = :id
[QxOrm] sql query (0 ms) : SELECT MyDerivedClass2.id AS MyDerivedClass2_id_0, MyDerivedClass2.prop1 AS MyDerivedClass2_prop1_0, MyDerivedClass2.prop2 AS MyDerivedClass2_prop2_0 FROM MyDerivedClass2 WHERE MyDerivedClass2.id = :id
[QxOrm] sql query (0 ms) : SELECT MyDerivedClass1.id AS MyDerivedClass1_id_0, MyDerivedClass1.description AS MyDerivedClass1_description_0 FROM MyDerivedClass1 WHERE MyDerivedClass1.id = :id
[QxOrm] sql query (0 ms) : SELECT MyContainer.id AS MyContainer_id_0, MyContainer.base_id AS MyContainer_base_id_0, MyContainer.base_type AS MyContainer_base_type_0 FROM MyContainer
[QxOrm] start dump 'QList<boost::shared_ptr<MyContainer>>'
<QList-boost.shared_ptr-MyContainer-- class_id="0" tracking_level="0" version="0">
   <count>3</count>
   <item class_id="1" tracking_level="0" version="1">
      <px class_id="2" tracking_level="1" version="0" object_id="_0">
         <id>1</id>
         <base_id>1</base_id>
         <base_type class_id="3" tracking_level="0" version="0">MyDerivedClass1</base_type>
         <base_ptr class_id="4" tracking_level="0" version="1">
            <px class_id="6" class_name="MyDerivedClass1" tracking_level="1" version="0" object_id="_1">
               <MyBaseClass class_id="5" tracking_level="1" version="0" object_id="_2">
                  <id>1</id>
               </MyBaseClass>
               <description>my desc modified</description>
            </px>
         </base_ptr>
      </px>
   </item>
   <item>
      <px class_id_reference="2" object_id="_3">
         <id>2</id>
         <base_id>1</base_id>
         <base_type>MyDerivedClass2</base_type>
         <base_ptr>
            <px class_id="7" class_name="MyDerivedClass2" tracking_level="1" version="0" object_id="_4">
               <MyBaseClass object_id="_5">
                  <id>1</id>
               </MyBaseClass>
               <prop1>my prop1</prop1>
               <prop2>my prop2</prop2>
            </px>
         </base_ptr>
      </px>
   </item>
   <item>
      <px class_id_reference="2" object_id="_6">
         <id>3</id>
         <base_id>1</base_id>
         <base_type>MyDerivedClass1</base_type>
         <base_ptr>
            <px class_id_reference="6" object_id="_7">
               <MyBaseClass object_id="_8">
                  <id>1</id>
               </MyBaseClass>
               <description>my desc modified</description>
            </px>
         </base_ptr>
      </px>
   </item>
</QList-boost.shared_ptr-MyContainer-->

[QxOrm] end dump 'QList<boost::shared_ptr<MyContainer>>'
QxOrm admin
 

Re: Can QxOrm persist pointers to abstract classes?

Postby QxOrm admin » Sun Jul 15, 2012 6:13 pm

Now, here is the solution if you want MyBaseClass to be an abstract class !
It's quite easy to do, you just have to not register it into QxOrm context.

MyBaseClass.h file :
Code: Select all
// ----------------------------------
// MyBaseClass.h

class QX_DLL2_EXPORT MyBaseClass : public qx::IxPersistable
{

public:

   long id;

   MyBaseClass() : qx::IxPersistable(), id(0) { ; }
   virtual ~MyBaseClass() = 0;

};

QX_REGISTER_ABSTRACT_CLASS(MyBaseClass)
QX_REGISTER_HPP_QX_DLL2(MyBaseClass, qx::trait::no_base_class_defined, 0)

typedef boost::shared_ptr<MyBaseClass> MyBaseClass_ptr;


MyBaseClass.cpp file :
Code: Select all
// ----------------------------------
// MyBaseClass.cpp

QX_REGISTER_CPP_QX_DLL2(MyBaseClass)

namespace qx {
template <> void register_class(QxClass<MyBaseClass> & t)
{
   t.id(& MyBaseClass::id, "id");
}}

MyBaseClass::~MyBaseClass() { ; }


And remove registration from MyContainer class, like this :
Code: Select all
namespace qx {
template <> void register_class(QxClass<MyContainer> & t)
{
   qx::IxDataMember * pData = NULL;

   pData = t.id(& MyContainer::id, "id");
   pData = t.data(& MyContainer::base_id, "base_id");
   pData = t.data(& MyContainer::base_type, "base_type");
}}


And you will obtain exactly the same output traces... ;)
QxOrm admin
 

Re: Can QxOrm persist pointers to abstract classes?

Postby achrislong » Mon Jul 16, 2012 4:47 pm

Hi,

Thanks very much for your help. That approach looks really promising.

Could you make that test project available as a zip or tarball somewhere, or email it to me?

Thanks!
achrislong
 
Posts: 4
Joined: Wed Jul 11, 2012 6:09 pm

Re: Can QxOrm persist pointers to abstract classes?

Postby achrislong » Mon Jul 16, 2012 7:51 pm

I'm guessing that it's not possible, but I would like to be able to declare relations to abstract types. Is there a way to do this?

Thanks!
achrislong
 
Posts: 4
Joined: Wed Jul 11, 2012 6:09 pm

Re: Can QxOrm persist pointers to abstract classes?

Postby QxOrm admin » Mon Jul 16, 2012 8:00 pm

Could you make that test project available as a zip or tarball somewhere, or email it to me ?

Just copy-past all classes I provide in my previous messages to the ./test/qxDllSample/dll2/ sample project...
If it doesn't work, wait for the next BETA version, I will add those classes to the dll2 project...

I'm guessing that it's not possible, but I would like to be able to declare relations to abstract types. Is there a way to do this ?

Nope, sorry for that ! No way to declare relations to abstract types.
QxOrm admin
 


Return to QxOrm - Help

Who is online

Users browsing this forum: No registered users and 6 guests