I just made a change to the database schema, but now the team needs it for my feature to work. How can I keep track of my database changes and communicate them to the rest of the team? Migrations give a structured way to structurally alter your database structure as your application evolves . . . structurally. They also provide a way for everyone on the team: developers, testers, CI admins, DBAs, etc, to apply the latest changes wherever they are needed - with uniformity and low friction. Fluent Migrations for .NET provide a discoverable, human readable API that supports dozens of different databases (including SQL Server, PostgreSQL, Oracle). Topics covered in this session:
* Why you should use migrations
* How to write fluent migrations
* A look behind the scenes of how fluent migrations work
* Drawbacks/downsides to using migrations
* Other migration options for EF and NoSQL (Couchbase)
Ad hoc SQL scripts make you want to flip a desk? Keep your team on the same page with fluent migrations.
(This session will briefly mention EF Migrations, but is not primarily about EF).
10. 10
What is Migration?
1. Write a script to make change(s) to a database schema
• E.g. "create a table" or "alter a table"
2. Script generally corresponds to a feature change in the code base
3. Commit the script with the feature change to source control
4. Run all scripts one-by-one and/or compile all scripts into a single script
NOT migration of data from one database to another
11. 11
Why use Migration?
• Version Control 📂⏰
• Automation ⚙⏰
• Documentation 📄📕
• Collaboration ⏰👥
16. 16
using FluentMigrator;
using System;
namespace YourCompany.YourProduct.Database.Maintenance
{
public class TagNames
{
public const string Development = nameof(Development);
}
[Tags(TagNames.Development)]
[Maintenance(MigrationStage.BeforeAll, TransactionBehavior.None)]
public class DevBeforeAll : ForwardOnlyMigration
{
public override void Up()
{
System.Console.WriteLine($"Tag=[{TagNames.Development}] Stage=[{MigrationStage.BeforeAll}]");
}
}
}
Maintenance Migrations
Run Logic Every Time
18. 18
/// <summary>
/// Mark all migrations with this INSTEAD of [Migration].
/// </summary>
public class MyCustomMigrationAttribute : FluentMigrator.MigrationAttribute
{
public MyCustomMigrationAttribute(int branchNumber, int year, int month, int day, int hour, int minute, string author)
: base(CalculateValue(branchNumber, year, month, day, hour, minute))
{
this.Author = author;
}
public string Author { get; private set; }
private static long CalculateValue(int branchNumber, int year, int month, int day, int hour, int minute)
{
return branchNumber * 1000000000000L + year * 100000000L + month * 1000000L + day * 10000L + hour * 100L + minute;
}
}
[MyCustomMigration(author: "Scott Stafford", branchNumber: 12, year: 2012, month: 8, day: 7, hour: 14, minute: 01)]
public class TestLcmpMigration : Migration
{
public override void Down() { /* ... */ }
public override void Up() { /* ... */ }
}
Enforce Version Numbering
One Standard for the Whole Team
19. 19
public class YourConventionSet : IConventionSet
{
public YourConventionSet() : this(new DefaultConventionSet()) { }
public YourConventionSet(IConventionSet innerConventionSet)
{
ForeignKeyConventions = new List<IForeignKeyConvention>()
{
/* This is where you do your stuff */
new YourCustomDefaultForeignKeyNameConvention(),
innerConventionSet.SchemaConvention,
};
ColumnsConventions = innerConventionSet.ColumnsConventions;
ConstraintConventions = innerConventionSet.ConstraintConventions;
IndexConventions = innerConventionSet.IndexConventions;
SequenceConventions = innerConventionSet.SequenceConventions;
AutoNameConventions = innerConventionSet.AutoNameConventions;
SchemaConvention = innerConventionSet.SchemaConvention;
RootPathConvention = innerConventionSet.RootPathConvention;
}
/// ... etc ...
}
Naming Conventions
What if my tables are named with GIANT_SNAKE_CASE?
23. 23
Top 5 Reasons NOT to use Fluent Migrator
Number 3 will SHOCK you
24. 24
Why NOT use FluentMigrator?
1. 💧 All Abstractions are leaky
5 Reasons
25. 25
Why NOT use FluentMigrator?
1. 💧 All Abstractions are leaky
2. ⏰It's C#. How does your DBA feel about it?
5 Reasons
26. 26
Why NOT use FluentMigrator?
1. 💧 All Abstractions are leaky
2. ⏰ It's C#. How does your DBA feel about it?
3. ⚙ Sprocs / views / triggers
5 Reasons
27. 27
Why NOT use FluentMigrator?
1. 💧 All Abstractions are leaky
2. ⏰ It's C#. How does your DBA feel about it?
3. ⚙ Sprocs / views / triggers
4. ♊Potential duplication of concerns
5 Reasons
28. 28
Why NOT use FluentMigrator?
1. 💧 All Abstractions are leaky
2. ⏰ It's C#. How does your DBA feel about it?
3. ⚙ Sprocs / views / triggers
4. ♊Potential duplication of concerns
5. 🎯 Database-specific features
5 Reasons
32. 32
Couchbase is a JSON database
SQL Server Couchbase Note
Server Cluster ➕ Scalability / High Availability / Built-in caching
Catalog (Database) Bucket
Schema Scope Often just "dbo" in SQL Server or "_default" in Couchbase
Table Collection ➖ Pre-defined columns/constraints
Row Document ➕ Flexible JSON
tSQL SQL++ (Previously known as N1QL in Couchbase)
Primary Key Document Key ➖ Compound keys
➖ "No" keys
Index Index
33. 33
NoSQL Support for Fluent Migrator?
Instead of
Create.Table(. . .)
what if there was
Create.Collection(. . .)
?