Schema upgrade |
||
From DataObjects.Net Wiki
|
Content of this section is outdated. Please refer to new DataObjects.Net Manual for actual information.
Schema upgrade overviewEvery time new Domain is built, schema upgrade is performed. Schema upgrade can be performed fully automatically, but in complex cases it requires assistance from developer - you can provide upgrade hints and/or write custom upgrade handler to implement complex schema upgrade. There are four different ways to upgrade a database schema, all of them are listed in DomainUpgradeMode enumeration:
You can specify upgrade mode in domain configuration. Upgrade steps in Perform \ PerformSafely modes
Implementing schema upgradeSpecifying name and version of your assemblyDataObjects.Net upgrade mechanism does not rely on regular assembly name and version. Instead it provides [AssemblyInfo] attribute that can be used to specify name and version of assembly exclusively for upgrade purposes. You should apply this attribute to each assembly with persistent types from the very first version of your code to make further upgrades possible. Usage of AssemblyInfoAttribute is simple. The following example is pretty self-describing. Using AssemblyInfoAttribute:
Please, note that version argument is a string. No special version string format is required. Writing custom upgrade handlerFirstly, to perform upgrade you need to write a custom upgrade handler. Upgrade handler is a class that inherits from UpgradeHandler class. Exactly one upgrade handler is required for each assembly that contain persistent types. If you do not specify upgrade handler default one is used. Upgrade handler should be placed in the same assembly it is written for and should have parameterless constructor. Upgrade mechanism will automatically detect upgrade handlers and instantiate them. UpgradeHandler base class contains many useful methods to override, but the most important are:
Using upgrade hintsUpgrade hints are one of the most important features of DataObjects.Net upgrade mechanism. Upgrade hint is a simple object that describe additional information about model changes to aid upgrader perform its tasks. Upgrade via upgrade hints sometimes called "semi-automatic upgrade". Here are the most common upgrade hints: Describes a renaming of a persistent type. You should create this hint when you rename entities or structures. Let's look how this hint is used. In first version of model we had Category entity, but in second version we decided to rename it to ProductGroup. Using RenameTypeHint:
As you can see the first argument of the constructor is a string, that represents a full name of the type being renamed. The second argument is a corresponding type from the new version of the model. Describes a renaming of a persistent field. You should create this hint when you rename a persistent field. As with previous example we renamed Category to ProductGroup. Also, we want to rename a field in Product entity to reflect this change. Let's rename Category field to Group. Again, creating of a hint is very simple. We specify the type that own a renamed field, old field name and new field name. It's important to note, that if you rename both type and field in this type, you should specify a new type in RenameFieldHint. Describes a moving of a persistent field within hierarchy. With this hint you can massively copy data from one entities to another. Imagine we have two persistent types Person and Customer. Customer inherits from Person. Customer have a string field ContactPhone. We want to move ContactPhone field to Person. Corresponding hint will look like this: Using CopyFieldHint:
We call constructor with three arguments: a name of the source type in the old model, a name of the field being copied, a destination type from the new model. There is optional fourth parameter. It is a name of the field in destination type that will receive the data. If not specified destination field name will be the same as source field name. It's important for source and destination types to have the same structure of key fields, because upgrade code will rely on primary keys to find association between source and destination rows in the database. Source and destination fields should either have the same primitive type, or have complex structure that produces the same set of primitive columns. For example you can easily copy entity reference fields that reference entities with the same Key structure. Now you know how to create upgrade hints. To add hints you need to override AddUpgradeHints method in your upgrade handler and add required hints to collection. The following code summarizes usage of upgrade hints. Using upgrade hints:
Firstly, we demand UpgradeContext and get its Hints property. Then we create hints and add them to the collection. Using RecycledAttributeThe second way to perform upgrade (so called "manual upgrade") is a manual copying data with aid of RecycledAttribute. This attribute can be applied to either persistenet property or persistent type. It marks its target as unused. Such property/type will not be available during normal work with persistent entities. But it will be available during upgrade stage, so you can use data to manually copy it somewhere. Let's imagine we have a persistent entity with the following structure (some members are omitted for clarity). Order entity:
Later we decided that Order won't contain Product and Amount directly, but instead it will posses a set of OrderItem entities each containing Product and Amount. Refactored Order entity:
We added [Recycled] attribute to Product and Amount properties. Also we added ObsoleteAttribute to both of them. It is not necessary to mark fields as obsolete but it will produce helpful warnings when these fields are accessed. Finally, we overriden OnUpgrade method to perform copying data. Both recycled and non-recycled properties are available inside this method. So data copying can be done easily - using your own entities. Using OnUpgrade method:
ExampleComplete source code demonstrating both "manual" and "semi-automatic" upgrades can be found in Schema upgrade sample (Xtensive.Storage.Samples.Upgrade) in DataObjects.Net distribution. |



