NShape supports scalable and flexible persistency for all its classes: Shapes, diagrams, templates, designs, styles and model objects. The persistency mechanism faces a series of true challenges to the design:
•It must be possible to integrate new shape and model object classes that can be persisted without any changes to the existing repository implementations.
•It must be possible to interact with any persistency mechanism the surrounding application may use.
•The default repository implementations must be flexible and fast enough for small and medium sized applications.
•It must be possible to implement an application-specific repository that achieves the best performance that is technically possible. In other words: The design and the implementation of the NShape framework must not restrict the performance of an adapted repository implementation.
•The persistency mechanism must support lazy loading, partial loading and incremental updates in order to scale well.
One important point among the aforementioned challenges is the independence of the shape implementations from the repository implementations. In order to achieve this, NShape works with three different data models instead of the usual two:
•The programming data model consists of the program code classes implementing Shape, IModelObject, Template, Design and IStyle. This data model has been defined by NShape and is therefore known to the framework. However, because it is based on all the features the Common Runtime offers, this data model is not well suited for serialization and persistency.
•The logical data model consists of the data model elements of the target store. In most cases the target store will be a relational database, which means that the logical data model are the tables, primary and foreign keys etc. of this RDBMS. This data model can be optimized by the client application for maximum performance and best fit for the requirements of that application. The framework however is completely ignorant of this data model.
•In between those two is the conceptional data model of the framework. It describes the persistable classes of the framework in a way better suited for persistency. It is defined by the framework and realized through a set of interfaces, e.g. IRepository and IEntity. Like the programming data model, the conceptual data model can be expanded by additional persistent classes. On the conceptual level, we talk about entities instead of shape types and other types to make clear, what we are talking about.
The mapping between the programming data model and the conceptual data model is performed in the IEntity.Load and IEntity.Save classes. Information about the entities is provided through shape types and the GetPropertyInfos methods of each of the persistable classes.
The default XML repository does not care about any logical data model and writes everything exactly like it is defined in the conceptual data model. It is however possible to write an additional XML repository, which works with a logical data model different from the conceptual one.
Set in one sentence, the responsibility of the repository is to map between the conceptual model and the logical model on the fly. The type of the repository determines how the diagramming objects are persisted. In an XML file, in a relational database or in an object-oriented database. To leverage special capabilities of a concrete RDBMS, there might be different implementations for SQL Server, Oracle, db4o etc.
When the repository is opened, it will typically open a connection to the respective database. The repository has methods for all queries required by the framework. It translates them to the respective query language (may be T-SQL, XQuery or any other) and executes them. The repository also creates live programming objects based on the query result data. During the work with these objects, the framework tells the repository when new objects have been created, when existing objects have been updated or deleted. Whenever the application wants it, the repository will write all modifications to the underlying physical store.
The framework comes with a repository that supports two different storage methods. One stores everything in an XML file and the other one is a customizable RDBMS repository, that can be used with any database for which a ADO.NET provider exists.