Persisting/saving objects
In object lingo, objects that are constructed new or loaded into a database are considered transient and when they are saved in a database they are considered persisted.
You have two options for saving objects to the database. A direct save or a unit of work.
DIRECT SAVE
A direct save is the easiest to implement, after constructing or updating an object, to persist it, you say:
var myMessages = myNebulaObject.Save();
if ( myMessages.isError )
// do error handing here
Always test the messages, because even without explicitly defined validation logic, the database may not persist your data due to an internal error.
UNIT OF WORK
Unit of Work is a pattern that allows you to save objects to a database as a set. When saving more than 10 objects at a time, you should consider this approach over a direct save as the save will be substantially faster.
A direct save operates by:
A unit of work operates by:
Fewer than 10 direct saves is faster than a unit of work, but beyond 10 the unit of work outpaces the direct save by huge orders of magnitude. 1000s of inserts can be done in less than 1 second.
To use a Unit of Work, the operation is nearly identical to your save. First, on all your domain objects you never call Save() directly. Instead, you call:
ValidationResult MESSAGES = Repository.Commit();
And it sets up an environment so that individual object saves (which it handles for you) occur within memory instead of being written to the database.
Dirty Flags
The term "dirty" means that the in-memory representation of the object is different from the database version. The unit of work uses the dirty flags to determine the order objects are written to the database. If you look inside the generated classes for attributes and master associations, you will discover this declaration:
public int Seed {
get { return _Seed; }
set {
if ( _Seed != value ) {
_Seed = value;
IsDirty = true;
}
}
}
protected int _Seed;
An protected attribute contains the actual value of the attribute, and a setter tests to see if the value actually changed before setting the "IsDirty" flag to true. Peering into the "IsDirty" flag, you'll find this logic:
public bool IsDirty {
get {
return _IsDirty;
}
set {
if (_IsDirty == false && value) {
_IsDirty = value;
Repository.RegisterUpdate(this);
}
}
}
private bool _IsDirty;
The order in which the dirty flag is set dictates the order that the Unit of Work writes the changes to the database. This allows you to intersperse inserts, updates and deletes in your logic without worrying if they are saved in the right order. In odd circumstances you might need to set an object's dirty flag before you actually change values on an object. In this case, IsDirty is public and you can set it directly.
You have two options for saving objects to the database. A direct save or a unit of work.
DIRECT SAVE
A direct save is the easiest to implement, after constructing or updating an object, to persist it, you say:
var myMessages = myNebulaObject.Save();
if ( myMessages.isError )
// do error handing here
Always test the messages, because even without explicitly defined validation logic, the database may not persist your data due to an internal error.
UNIT OF WORK
Unit of Work is a pattern that allows you to save objects to a database as a set. When saving more than 10 objects at a time, you should consider this approach over a direct save as the save will be substantially faster.
A direct save operates by:
- opening the database
- writing the changes to disk
- closing the database
A unit of work operates by:
- opening the database
- loading all the appropriate database parts into memory that are being updated
- write all the changes to the database, in memory
- at the end, saving all the changed database parts to disk
- closing the database
Fewer than 10 direct saves is faster than a unit of work, but beyond 10 the unit of work outpaces the direct save by huge orders of magnitude. 1000s of inserts can be done in less than 1 second.
To use a Unit of Work, the operation is nearly identical to your save. First, on all your domain objects you never call Save() directly. Instead, you call:
ValidationResult MESSAGES = Repository.Commit();
And it sets up an environment so that individual object saves (which it handles for you) occur within memory instead of being written to the database.
Dirty Flags
The term "dirty" means that the in-memory representation of the object is different from the database version. The unit of work uses the dirty flags to determine the order objects are written to the database. If you look inside the generated classes for attributes and master associations, you will discover this declaration:
public int Seed {
get { return _Seed; }
set {
if ( _Seed != value ) {
_Seed = value;
IsDirty = true;
}
}
}
protected int _Seed;
An protected attribute contains the actual value of the attribute, and a setter tests to see if the value actually changed before setting the "IsDirty" flag to true. Peering into the "IsDirty" flag, you'll find this logic:
public bool IsDirty {
get {
return _IsDirty;
}
set {
if (_IsDirty == false && value) {
_IsDirty = value;
Repository.RegisterUpdate(this);
}
}
}
private bool _IsDirty;
The order in which the dirty flag is set dictates the order that the Unit of Work writes the changes to the database. This allows you to intersperse inserts, updates and deletes in your logic without worrying if they are saved in the right order. In odd circumstances you might need to set an object's dirty flag before you actually change values on an object. In this case, IsDirty is public and you can set it directly.