-
Notifications
You must be signed in to change notification settings - Fork 25
Maintenance
NOTE! Ensure you have a backup of your DB and try it on a development environment first.
As of v11.0.0 there's a new maintenance API, which replaces Db.GetStructureSetMigrator
. Available operations are:
- Reset -
Db.Maintenance.Reset();
- RenameStructure -
Db.Maintenance.RenameStructure("OldName", "NewName");
- RegenerateQueryIndexesFor -
Db.Maintenance.RegenerateQueryIndexesFor<T>()
- Migrate -
Db.Migrate<TFrom, TNew>(Func<TFrom, TTo, MigrationStatuses> modifier)
- Migrate -
Db.Migrate<TFrom, TTo>(Func<TFrom, TTo, MigrationStatuses> modifier)
- Migrate -
Db.Migrate<TFrom, TFromTemplate, TTo>(Func<TFrom, TTo, MigrationStatuses> modifier)
Maintenance operations are accessible via Maintenance
on a db-instance. Below is the documentation for all included operations.
Db. Maintenance.Reset()
will look in the database for all tables ending with below suffixes; and then drop them:
- Structure
- Uniques
- Integers
- Fractals
- Booleans
- Dates
- Guids
- Strings
- Texts
All tables that has any of the above suffixes WILL BE DROPPED. Hence if you add a custom table, not being a SisoDb table, e.g "MyGoofyStrings"; it will also be dropped.
Lets you rename a structure. E.g Db.Maintenance.Rename("Persons", "People")
will rename included tables, primary keys, foreign keys etc.
Will drop all existing query-indexes and regenerate them from the structures stored in db. E.g Db.Maintenance.RegenerateQueryIndexesFor<Person>()
The migration operations lets you migrate data. Either from one model to another or within the same model. Hence, you could do migrations like:
- Person --> SalePerson
- Person --> Person
When doing migrations within the same type, e.g Person --> Person
you don't even need to have the old-model at hand, since you can use the overload taking TFromTemplate
. That way you could pass an anonymous type if you like. Otherwise, just have a migrations assembly and put the old model in there.
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.
In this case you should really use Db.Maintenance.RenameStructure
instead, but the migrations API will assist you with this as well. And if the new structure is compatible with the JSON you don't have to provide any manual mappings just return MigratorStatuses.Keep
so that SisoDb will insert the new item in the new structureset.
(oldItem, newItem) => MigratorStatuses.Keep;
The TNew item has the new property and you will need to map it manually:
(oldItem, newItem) =>
{
newItem.NewProperty = oldItem.OldPropery;
return MigratorStatuses.Keep;
}
I'll just let the example speak for it self.
Old 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
}
New 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 using Func
db.Maintenance.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 MigratorStatuses.Keep;
});
How-to do it using Migration
db.Maintenance.Migrate(Migrate<Person>.To<SalesPerson>().Using(
(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 MigratorStatuses.Keep;
}));
By letting you use anonymous objects in your migrations you don't need to sit on an old representation of the model.
Old model
public class Car
{
public string RegNo { get; set; } //Change: Rename
public string Type { get; set; } //Change: Split
}
New model
public class Car
{
public string RegistrationNumber { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public string Type { get; set; }
}
Given
new Car
{
RegNo = "ABC123",
Type = "Volvo V50 Deluxe"
}
We want
new Car
{
RegistrationNumber = "ABC123",
Make = "Volvo",
Model = "V50",
Type = "Deluxe"
}
How-to do it using Migration using anonymous object
Note! In the code below Car
is of the new model. The anonymous object represents the old model.
db.Maintenance.Migrate(Migrate<Car>.To<Car>().Using(
new
{
RegNo = default(string),
Type = default(string)
},
(oldItem, newItem) =>
{
newItem.RegistrationNumber = oldItem.RegNo;
var makeModelType = oldItem.Type.Split(' ');
newItem.Make = makeModelType[0];
newItem.Model = makeModelType[1];
newItem.Type = makeModelType[2];
return MigratorStatuses.Keep;
}));