Signum Framework Logo
"Open framework that encourages convention over configuration, using C# code,
not XML files, to model at the right level of abstraction and achieve deadlines.
...but also has a full Linq provider, and syncs the schema for you!"



Source code




Saving is the process of storing entities in the database, inserting them if they are new, or updating them if they are already there.

When an entity is saved for the first time, an Id is assigned to it.

Saving has full support for graphs of entities, so you can have a graph of IdentifiableEntity with cycles and the saver should be able to deal with it.

Also, in the current implementation, saving is done at a granularity level of the IdentifiableGraph, so it's not possible to save just a Modifiable (an EmbeddedEntity or a MList for example). In fact, when a Modifiable is SelfModified, the modification is propagated to the parent IdentifiableEntity before saving, so the whole IdentifiableEntity is saved. See more about this in Change Tracking.

Before saving, every Modifiable is tested for integrity using IntegrityCheck. If the test fails, an Exception is thrown and the transaction is roll-backed, so you never have invalid data in your database. You can avoid this behaviour for some particular entities and integrity rules using Corruption. See more about this in Validation.

Finally, before saving, the method PreSaving is called on every Modifiable in the graph. You can use it to calculate some redundant values before saving (ToStr is calculated this way).

Save Overloads

//Simple overload for saving an entity. Modifies the entity by reference, calling PreSaving and assigning Id if it's new, and returns the entity itself.   
public static T Save<T>(this T obj) where T : IdentifiableEntity

//Same as above but for saving IEnumerables of entities. Nice when creating entities using Linq queries. public static void SaveList<T>(this IEnumerable<T> entities) where T : IIdentifiable

//Saving some random entities at once. public static void SaveParams(params IdentifiableEntity[] entities)

Preserving Object Identity

Once saved, entities are stored in the current ObjectCache. This information is usually lost but you can keep it using a wider scope ObjectCache.

How the Saver works (Advanced Topic)

In case you are interested in the details, this is what the saver is actually doing:

  1. Generating a DirectedGraph of all the reachable Modifiables.
  2. Testing IntegrityCheck and calling PreSaving on every Modifiable.
  3. Using an invert graph to propagate modifications from Modifiables to the closest Identifiable parent.
  4. Collapsing the original graph of Modifiables to a graph of Identifiables.
  5. Identifying all the edges that mean a dependency on saving order (the end of the edge goes to a new Identifiable).
  6. Identifying feedback edges, if any, in this dependency graph using this algorithm.
  7. Grouping Identifiables in the graph using topological short, so the entities are layered starting from the leaves and ending with the root.
  8. Saving each group (layer): The Schema class is the one that actually creates the SqlPreCommand for each entity avoiding to use references in the feedback edge set. Finally the SqlPreCommands are concatenated together and sent to the database using a single SqlCommand. If some group is too big for a single Sql Command (too many parameters), this is split using SqlPreCommand facilities.
  9. Final updates are sent to fix the problem made by the feedback edges.

Note: Maybe you have realised that, in order to resolve cycles, entities have to be saved inconsistently while some related entities have no Id jet (feedback edges). This is safely done inside of a transaction but could have problems if your FK columns have no support for null values. Try to avoid [NotNullable] atributte on references, use [NotNullValidator] on the property instead.
Creative Commons License Signum Framework Site by Signum Software is licensed under a Creative Commons Attribution 3.0 License.
Powered by ScrewTurn Wiki version