-
Notifications
You must be signed in to change notification settings - Fork 25
Model updates
Since SisoDb stores the object graph representation as JSON and as a flattened object in the Indexes-table using key-values in the Indexes table, you could of course update the values in the Indexes-table using T-SQL and also try to update the JSON member using T-SQL, but sometimes you might want to perform more advances updates, and then you do basically do have to re-save the structures, and there's a method to facilitate this for you.
Whenever a new property in the graph is introduced, the values will be inserted in the Indexes-table upon the next insert and in the Uniques-table as well if you have marked them as unique.
If you remove a property in the graph, the values from the Indexes-table and the Uniques-table will be deleted. The value will still reside in the JSON-structure, until the next time the item is updated.
There's functionality to assist you with schema changes of more complex nature, e.g:
- Rename structure
- Rename properties
- Split one property to several
- and more...
To do this, you use:
db.CreateStructureSetMigrator().Migrate<TOld, TNew>(Func<TOld, TNew, StructureSetMigratorStatuses> migrator);
As long as the underlying provider supports it (e.g Sql2008, SqlCe4) all changes are performed within transactions, hence datachanges can be rollbacked. All items are read back as json and then deserialized to both the TOld and TNew items which then are injected to a modifier func, where you perform the changes and return a status indicating what you want todo with the structure.
The modifier
can return three different values:
- Keep: Indicates that you want to keep the structure and the new-structure will be persisted with the same id as the old.
- Trash: Indicates that your are no longer interested in keeping the structure, hence it will be deleted.
- Abort: Abort and rollback the process.
You do need to have an entity in your model that is compatible with the Old entity. This old entity needs to be there for reading up entities from the old structure hence it need to be compatible with the json structure (at least the members you want to keep)
Store the old model items in a project used only for updating a production environment. E.g in a console app and then add a reference to the new model to this app and use this application to apply the changes.
There will be a dynamic structure available in the future, which you then can use for performing model updates without the need of the old model.
If the new structure is compatible with the Json you don't have to provide any manual mappings just return StructureSetMigratorStatuses.Keep
so that SisoDb will insert the new item in the new structureset.
(oldItem, newItem) => StructureSetMigratorStatuses.Keep;
The TNew item has the new property and you will need to map it manually:
(oldItem, newItem) =>
{
newItem.NewProperty = oldItem.OldPropery;
return StructureSetMigratorStatuses.Keep;
}
I'll just let the example speak for it self.
New model
public class Person //Change: Rename
{
public Guid Id { get; set; }
public string Name { get; set; } //Change: Split
public string Address { get; set; } //Change: Split
public string HairColor { get; set; } //Change: Drop
}
Old model
public class SalesPerson
{
public Guid Id { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public Address Office { get; set; }
public SalesPerson()
{
Office = new Address();
}
}
public class Address
{
public string Street { get; set; }
public string Zip { get; set; }
public string City { get; set; }
}
Given
new Person
{
Name = "Daniel Wertheim",
Address = "The Street 1\r\n12345\r\nThe City",
HairColor = "Black"
};
We want
new SalesPerson
{
Firstname = "Daniel",
Lastname = "Wertheim",
Office = new Address
{
Street = "The Street 1",
Zip = "12345",
City = "The City"
}
};
How-to do it
db.CreateStructureSetMigrator().Migrate<Person, SalesPerson>(
(p, sp) =>
{
var names = p.Name.Split(' ');
sp.Firstname = names[0];
sp.Lastname = names[1];
var address = p.Address
.Split(new[]{"\r\n"}, StringSplitOptions.RemoveEmptyEntries);
sp.Office.Street = address[0];
sp.Office.Zip = address[1];
sp.Office.City = address[2];
return StructureSetMigratorStatuses.Keep;
});