NShape Programmer Tasks
Implementing the Save Method

<< Click to Display Table of Contents >>

Navigation:  Programmer Tasks > Developing a New Shape Class > Adding Persistency Support >

NShape Programmer Tasks
Implementing the Save Method

Previous pageReturn to chapter overviewNext page

The save methods of the IEntity interface uses the write methods of IRepositoryWriter to write the fields of the persisted object. The following rules must be observed:

Never write the id of the object, this is done by the repository.
Always write all persistent fields of the object. Do not skip unmodified fields etc.
The order of the fields to write must be the same as in GetPropertyDefinitions.

Implementing SaveFields

In order to save objects to a repository, just implement all save methods of the interface, preferably as explicit implementation:

void IEntity.SaveFields(IRepositoryWriter writer, int version) {
 reader.WriteInt32(MyIntProperty);
 reader.WriteString(MyStringProperty);
 if (version >= 2)
         reader.WriteStyle(MyColorStyleProperty);
}

For all base classes of the NShape framework, there are Core methods of the IEntity methods because you cannot override explicit implementations. Override the appropriate Core methods in this case:

protected override void SaveFieldsCore(IRepositoryWriter writer, int version) {
 base.SaveFieldsCore(reader, version);
 writer.WriteInt32(MyIntProperty);
 writer.WriteString(MyStringProperty);
 if (version >= 2)
         writer.WriteStyle(MyColorStyleProperty);
}

Implementing SaveInnerObjects

The same for the inner objects: Implement the IEntity interface explicitly or override the appropriate methods of the base class. If your class does not contain complex objects or lists that have to be saved, you don't have to bother with this method.

A notable difference to the SaveFields implementation is the fact that inner objects can also be list of objects and therefore the saving has to be done in loops. In addition to that, saving inner objects has to be started with a call to BeginWriteInnerObjects and ended with a call to EndWriteInnerObjects of the given IRepositoryWriter. Similarly, each saving of an inner object has to be surrounded by BeginWriteInnerObject and EndWriteInnerObject.

protected override void LoadInnerObjectsCore(string propertyName, IRepositoryReader reader, int version) {
 if (propertyName == "MyInnerObjects") {
         // Clear list of inner objects
         innerObjects.Clear();
         // Load inner objects
         reader.BeginReadInnerObjects();
         while (reader.BeginReadInnerObject()) {
                 int intValue = reader.ReadInt32();
                 string strValue = reader.ReadString();
                 InnerObjects.Add(new MyInnerObject(intValue, strValue);
                 reader.EndReadInnerObject();
         }
         reader.EndReadInnerObjects();
 } else base.LoadInnerObjectsCore(propertyName, reader, version);
}

See Also

Concepts: Persistency

Working with NShape: Adding persistency support

 

For all classes with inner objects, the save method must be implemented in two parts: SaveData and SaveInnerObjects. The first one saves all fields of the object itself while the second one saves the inner objects i.e. objects which have a composition with the current object.

Implementing SaveFields

The typical SaveFields method looks like this:

void SaveFields(IRepositoryWriter writer, int version) {
 writer.WriteString(name);
 writer.WriteInt32(count);
 writer.WriteDate(date);
}

 

Implementing SaveInnerObjects

SaveInnerObjects is called after SaveData and its task is to write all composite objects within the persistable object.

SaveInnerObjects uses the methods BeginWriteInnerObjects/EndWriteInnerObjects and BeginWriteObject/EndWriteObject to write inner objects.

The typical implementation looks like this:

void SaveInnerObjects(IRepositoryWriter writer, int version) {
 BeginWriteInnerObjects("Point");
 foreach (Point p in points) {
         IRepositoryWriter innerWriter = BeginWriteObject();
         innerWriter.WriteInt16(p.x);
         innerWriter.WriteInt16(p.y);
         EndWriteObject();
 }
 EndWriteInnerObjects();
 //
 BeginWriteInnerObjects("Pattern");
 foreach (Pattern p in patterns) {
         IRepositoryWriter innerWriter = BeginWriteObject();
         pattern.Save(innerWriter, version);
         EndWriteObject();
 }        
 EndWriteInnerObjects();
}

See Also

Concepts: Persistency

Working with NShape: Adding persistency support