SQLiteMigrations is a .NET Standard Library for use with SQLite-net that allows you to manage database migrations using the PRAGMA option
Install Vitvov.SQLiteMigrations from NuGet.
Let's say you have a database table
[Table("record")]
public class RecordEntity
{
[PrimaryKey, AutoIncrement]
[Column("id")]
public long Id { get; set; }
[Column("startTime")]
public DateTime StartTime { get; set; }
[Column("endTime")]
public DateTime EndTime { get; set; }
}
In order to create a database, you must create a class that implements SQLiteAsyncDatabase
.
You will have access to the public property Connection
of type SQLiteAsyncConnection
.
In the CreateAsync()
method, write the database creation script.
Return null
in the Migrations()
method.
public class AppDatabase : SQLiteAsyncDatabase
{
private const int DB_VERSION = 1;
public AppDatabase(string path) : base(DB_VERSION, path)
{
}
public override async Task CreateAsync()
{
await Connection.CreateTableAsync<RecordEntity>();
}
public override List<IMigration> Migrations()
{
return null;
}
}
To access tables, use the Connection
property. For example, you can add a property to your class
public class AppDatabase : SQLiteAsyncDatabase
{
// some code ...
public AsyncTableQuery<RecordEntity> RecordsTable => Connection.Table<RecordEntity>();
}
To start working with the AppDatabase, call
var dbPath = Path.Combine(FileSystem.AppDataDirectory, "db.sqlite");
var database = new AppDatabase(dbPath);
await database.ConnectAsync();
//usage
//database.Connection.Table<RecordEntity>()...
Let's say you want to add a new table
[Table("data")]
public class DataEntity
{
[PrimaryKey, AutoIncrement]
[Column("id")]
public long Id { get; set; }
[Column("pulse")]
public int Pulse { get; set; }
[Column("recordId")]
public long RecordId { get; set; }
}
Let's create a migration for our database. Create a new migration class and implement the IMigration
interface
public class Migration1To2 : IMigration
{
public int OldVersion => 1;
public int NewVersion => 2;
public void Migrate(SQLiteConnection connection)
{
connection.CreateTable<DataEntity>();
}
}
And also make a change to the database class
public class AppDatabase : SQLiteAsyncDatabase
{
private const int DB_VERSION = 2; // <- change version from 1 to 2
public AppDatabase(string path) : base(DB_VERSION, path)
{
}
public override async Task CreateAsync()
{
await Connection.CreateTableAsync<RecordEntity>();
await Connection.CreateTable<DataEntity>(); // <- add line
}
public override List<IMigration> Migrations()
{
// <- return the migration
return new List<IMigration>
{
new Migration1To2()
};
}
}
Let's say you want to add a new field to the RecordEntity table
[Table("record")]
public class RecordEntity
{
// some code...
// new property
[Column("recorder")]
public string RecorderName { get; set; }
}
Let's create a migration for our database
public class Migration2To3 : IMigration
{
public int OldVersion => 2;
public int NewVersion => 3;
public void Migrate(SQLiteConnection connection)
{
connection.Execute("ALTER TABLE record ADD COLUMN recorder VARCHAR");
}
}
And also make a change to the database class
public class AppDatabase : SQLiteAsyncDatabase
{
private const int DB_VERSION = 3; // <- change version from 2 to 3
public AppDatabase(string path) : base(DB_VERSION, path)
{
}
public override async Task CreateAsync()
{
await Connection.CreateTableAsync<RecordEntity>();
await Connection.CreateTable<DataEntity>();
}
public override List<IMigration> Migrations()
{
return new List<IMigration>
{
new Migration1To2(),
new Migration2To3()// <- add new line
};
}
}
To use your own connection string, pass it to the base class constructor.
public class AppDatabase : SQLiteAsyncDatabase
{
public AppDatabase(SQLiteConnectionString сonnectionString) : base(DB_VERSION, сonnectionString)
{
}
}
var options = new SQLiteConnectionString(databasePath);
var database = new AppDatabase(options);
await database.ConnectAsync();