Please note: this project is inactive since early 2006

 
B.1 Designing the model

What if I want to move my package/modules to another package/location/whatever after it has been generated?

If, after generation of code, you need to move the generated package to some other package, or if you need to move a class to some other module, just adjust you model to reflect your change. The following adjustments should be made:

The only limitation is that all classes corresponding to entities in a model should be located within the same package (the one identified by the field 'packageName' in model's properties).

What if I want to see the primary key values in my objects?

Making it a class property
Really, you should not -simply because we do not support anything but automatic generation of simple primary key (one attribute only, no compound primary keys), you shouldn't need to expose the PK values as class' attributes. But, ok, if you really want to do that, that is to say, if you declare them as class properties:
  • you must also define a default value of 0 (integer zero)
  • please keep in mind that they should be considered READ-ONLY ; if you modify them at run-time, the framework will not even notice that-it just does not expect it-and things will be out-of-control, for sure. You've been warned!

Using CustomObject.snapshot_raw()

This method is the best way to get the values that will be stored for an object at a given state in the database when changes are saved. It returns a dictionary from which the value of the primary key can be retrieved. Be sure to carefully read its documentation before using it.

This method does not require that the primary key is made a class property.

Accessing it at run-time
There's a third alternative: the primary key value can always be retrieved from your objects, without requiring it to be a class property and apart from snapshot_raw(). You can access it with globalID; every single object managed by the framework is uniquely identified by its global id. Among other things, this one has a dictionary holding the PK values:

>>> object=ec.fetch('Writer', qualifier='age<50')[0]
>>> object.globalID().keyValues()
{'id': 1}

So if you need to access the PK for objects of a given class, you can add a method like this one:

  def pk(self):
    "Returns the pk's value"
    gid=self.globalID()
    if not gid:
      return None
    if gid.isTemporary():
      # temporary gid: object has been inserted but not saved yet.
      # Change this to return any value you find more appropriate
	return gid
    return gid.keyValues()['id']

Note: CustomObject.globalID() can return None when an object has just been inserted into an EditingContext but has not been saved yet.

What if I want to see the foreign key values in my objects?

As a general rule, foreign keys should not be made class properties; this is an even stricter rule than the one for primary keys, because the framework does not update foreign keys values in objects that define them as class properties (but of course, they will saved as expected in the database).

The reason is that a foreign key is usually used to store the piece of information needed to store in the database a to-one relationship at the object level. Say you have an entity, Writer related with the entity Book in a one-to-many relationship; the table for entity Book stores the primary key value for the corresponding Writer in a foreign key FK_Writer_id. Suppose now that a book is moved from one author to another: at the object-level, the book is removed to one author's set of books and added to the others, while the book itself gets a new author:

>>> writer1.removeFromBooks(book)
>>> book.setAuthor(writer2)
>>> writer2.addToBooks(book)

If the foreign key Book.FK_Writer_id is a class property, it is now out of sync with the book's author, because it stores the former author's id while it has been assigned to an other one.

However, there are several alternate solutions for accessing a foreign key value, if you really insist on doing this:

Using CustomObject.snapshot_raw()
This particular method was especially design for that purpose, as it returns the raw data that do/will represent the corresponding database row. As far as foreign keys are concerned, it tries everything possible to return a foreign key value reflecting the current state of the graph of object. There are, however, situations where the returned value can get out-of-sync; please refer to the documentation of CustomObject.snapshot_raw() for details.

Explicitely extracting the related objects's primary key

You can also do it manually, by traversing the relationship to get its primary key, for example by adding such a method to your Book:

   def getFKWriterId(self):
     if self.getWriter() is None:
       return None
     else:
       w_gid=self.getWriter().globalID()
       if w_gid.isTemporary():
         # temporary gid: object has been inserted but not saved yet.
         # Change this to return any value you find more appropriate
         return w_gid
       else:
         return w_gid.keyValues()
This code is, in fact, the relevant part of the code of CustomObject.snapshot_raw(). It's exposed here so that you can see the different cases that can happen. Of course, it assumes that a to-one relationship for this foreign key is defined in the object's entity -if the FK is only involved in an other entity's to-many relationship with no inverse, there's little to do, except relying on CustomObject.snapshot_raw() (see above) that can also retrieve the correct FK value after the first fetch, and after the EditingContext saved its changes. Please refer to its documentation for full details.

Comments are welcome: Sebastien Bigaret / Modeling Home Page
Hosted by:SourceForge.net Logo