SQLiteCodeFirst: code first SQLite for Entity Framework 6
Creates a SQLite Database based on a EdmModel by using Entity Framework CodeFirst.
At a glance
- What is it?
- SQLiteCodeFirst fills the gap where Entity Framework 6 offers no code first support for SQLite, by reading your EdmModel and generating the database. The author is explicit that on .NET Core 3 or later with EF Core you do not need it at all, which makes the adoption case narrower and clearer than most library pages.
- Who is it for?
- Adopt SQLiteCodeFirst only if you are on Entity Framework 6, either on .NET Full Framework or on .NET Core 3 and above, and you want code first creation of a SQLite database without EF Core. Do not adopt it for a new EF Core project, because EF Core already supports code first and migrations for SQLite and the author says so plainly.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A library that exists to fill one specific gap in EF6
SQLiteCodeFirst creates a SQLite database from code, using Entity Framework code first. The project description says it creates a SQLite Database based on an EdmModel by using Entity Framework CodeFirst.
The reason it exists is stated more plainly than most library pages manage. The project was started when there was .NET Full Framework and EF 6, and EF 6 does not offer code first for SQLite. This library fills that gap.
Then comes the passage that decides whether you need it at all. Nowadays there is .NET Core, now called just .NET, and EF Core, and EF Core supports code first and migrations for SQLite. If you use .NET Core 3 or above together with EF Core, there is no need for this library. If you use EF 6, either with .NET Full Framework or with .NET Core 3 or above, this library is an option for you to get code first for SQLite.
That is an unusual thing for a maintainer to write about their own project, and it is the most useful paragraph in the README. A library that tells you when not to use it is a library that has thought about its own scope.
The maintenance commitment is similarly plain. The author says he is going to maintain the library as long as it is useful for some people, and links to a history discussion and a project status and release schedule issue for the details. The last push to the repository was on 2026-10-19, the releases are v1.8.0 and v1.7.1 both on 2026-06-16 with v1.7.0.36 from 2024-02-23, and the licence is Apache-2.0.
So the shape of the project is: a narrow, still-maintained, permissive licence library serving people on a framework generation that predates EF Core.
The three initializers and the two lower level escape hatches
The functionality is exposed through implementations of the IDbInitializer interface, and the choice between them is a policy decision about when your database gets rebuilt.
The three initializers are SqliteCreateDatabaseIfNotExists, SqliteDropCreateDatabaseAlways and SqliteDropCreateDatabaseWhenModelChanges. The first creates the database only if it is not there, the second drops and recreates on every run, and the third drops and recreates when the model has changed.
The interesting one is the third, and the documentation explains its cost. The SqliteDropCreateDatabaseWhenModelChanges initializer creates an additional table in your database, used to store information to detect model changes. If you want to use your own entity or table instead, you have to implement the IHistory interface and pass the type of your entity as a parameter to the constructor of the initializer.
That is a real operational detail. The convenient option writes a table the framework owns, and the clean option requires you to supply an entity and implement an interface.
Below the initializers there are two lower level entry points. SqliteDatabaseCreator implements IDatabaseCreator and lets you control the creation of the SQLite database directly. SqliteSqlGenerator implements ISqlGenerator and lets you generate the SQL code based on your EdmModel, which is the hook you want if you need to see or adjust the DDL itself.
For the ordinary case, the documentation is brief: set SqliteDropCreateDatabaseAlways or SqliteCreateDatabaseIfNotExists as your IDbInitializer and Entity Framework creates the database if it does not exist.
Wiring it up in a DbContext and seeding after creation
The initializer sample shows the whole integration in one method. The initializer is constructed with the model builder and then registered with Database.SetInitializer:
public class MyDbContext : DbContext
{
public MyDbContext()
: base("ConnectionStringName") { }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var sqliteConnectionInitializer = new SqliteCreateDatabaseIfNotExists<MyDbContext>(modelBuilder);
Database.SetInitializer(sqliteConnectionInitializer);
}
}The generic parameter is the context type, which is how the initializer knows which model to build the schema from. The DbModelBuilder argument is the EF6 model builder passed in from OnModelCreating, and the connection string is referenced by name in the base constructor call.
Seeding is the second mechanism, and it is opt in by inheritance rather than by configuration. You inherit from one of the three initializers and override the Seed method:
public class MyDbContextInitializer : SqliteDropCreateDatabaseAlways<MyDbContext>
{
public MyDbContextInitializer(DbModelBuilder modelBuilder)
: base(modelBuilder) { }
protected override void Seed(MyDbContext context)
{
context.Set<Player>().Add(new Player());
}
}The documentation specifies two conditions for the seed to run. It is called in a transaction, once the database was created, and it is only executed if a new database was successfully created. That second point matters for the WhenModelChanges initializer, where the database may not be recreated at all, so the seed simply does not fire on most runs.
The stated use case is populating core or test data after the database was created, which is a good fit for a demo database or a test fixture where you want the schema and a known row in one step.
The annotation surface, and the attributes that exist because EF6 cannot express them
The supported feature list reads like a mapping table from Entity Framework annotations onto SQLite DDL, and the interesting entries are the ones where a gap had to be filled.
Tables come from classes with the Table annotation. Columns come from properties, with support for Column, Key, MaxLength, Required, NotMapped, DatabaseGenerated and Index. The PrimaryKey constraint comes from the Key annotation, and composite keys are supported. The ForeignKey constraint covers 1-n relationships, with support for cascade on delete and cascade on update. The Not Null constraint is supported, and auto increment is automatic for an int primary key, with an explicit AUTOINCREMENT constraint available through an Autoincrement attribute.
Then come the parts where the library had to add something Entity Framework does not have. A Unique constraint comes from a UniqueAttribute, which the documentation notes is part of this library. A Collate constraint comes from a CollateAttribute, also part of this library, and you can use CollationFunction.Custom to specify your own collation function. A default collation can be passed as a Collation constructor parameter to an initializer. An SQL default value comes from a SqlDefaultValueAttribute, also part of this library.
The last one is the most instructive. Cascade on update comes from a CascadeOnUpdateAttribute, and the explanation is precise: Entity Framework cannot express ON UPDATE CASCADE, so this opt-in attribute must be placed on the dependent foreign key property, such as TeamId, and not on the navigation property. It also requires an explicit foreign key property.
That is a good illustration of the general shape of this library. EF6 has a rich object model but SQLite is a narrower database, and the gap is closed with small attributes rather than with a new abstraction.
Indexes are created automatically for foreign keys by default, and you can prevent that by removing the ForeignKeyIndexConvention.
Installing it, the target frameworks, and the repository layout
Installation is either the assembly from the GitHub release page or the NuGet package SQLite.CodeFirst, installed with the Package Manager Console command Install-Package SQLite.CodeFirst.
The project is built to target .NET framework versions 4.0 and 4.5 and .NET Standard 2.1, and the README lists where you can use it from. .NET 4.0 uses the net40 build, .NET 4.5 to 4.8 uses net45, .NET Core 3.0 to 3.1 uses netstandard2.1, and .NET 5 and later including .NET 10 also uses netstandard2.1.
That table answers the practical question for most people, since the netstandard2.1 asset covers modern .NET even though the library is fundamentally an EF6 tool. You can consume it from a current runtime, but you are still on EF6's object model and its DbModelBuilder-based API, which is the thing that dates the library.
The repository layout shows how small and focused the project is. There is a SQLite.CodeFirst directory for the library, a SQLite.CodeFirst.Test directory for the tests, and two console projects, SQLite.CodeFirst.Console and SQLite.CodeFirst.NetCore.Console, which are almost certainly there to exercise the library against both EF6 on .NET Framework and EF6 on .NET Core. There is a Shared directory, a Directory.Build.props for shared MSBuild properties, a global.json pinning the SDK, a solution file in the newer slnx format, and a .nuget directory. The .github directory holds both a CI workflow and a CD workflow, so packaging to NuGet is automated.
The project is open to contributions, and the README asks for stars, issue reports, pull requests or a donation, with a specific note that a donation is welcome especially if you use it for a commercial project, and that a paid implementation is available if you need a specific feature for one. The support option is part of the project's model, which is a reasonable arrangement for a library whose main users are on a framework generation that is out of support.
Editorial conclusion
Adopt SQLiteCodeFirst only if you are on Entity Framework 6, either on .NET Full Framework or on .NET Core 3 and above, and you want code first creation of a SQLite database without EF Core. Do not adopt it for a new EF Core project, because EF Core already supports code first and migrations for SQLite and the author says so plainly. Before you start, check whether your target framework is covered, since the package targets .NET 4.0, .NET 4.5 to 4.8 and .NET Standard 2.1, and decide which initializer you need, because SqliteDropCreateDatabaseWhenModelChanges writes an extra table to detect model changes unless you supply your own IHistory entity.
Frequently asked questions
Do I need SQLiteCodeFirst if I use EF Core on .NET Core 3 or later?
No. The project states that EF Core supports code first and migrations for SQLite, and that if you use .NET Core 3 or above with EF Core there is no need for this library. It exists for EF 6 users, on .NET Full Framework or on .NET Core 3 and above.
Which initializers does SQLiteCodeFirst provide?
SqliteCreateDatabaseIfNotExists, SqliteDropCreateDatabaseAlways and SqliteDropCreateDatabaseWhenModelChanges, all implementing IDbInitializer. Below them are SqliteDatabaseCreator implementing IDatabaseCreator and SqliteSqlGenerator implementing ISqlGenerator for direct control over creation and SQL generation.
How do I seed data after the database is created?
Inherit from one of the initializers and override the Seed method with your context. It is called in a transaction once the database was created, and only if a new database was successfully created.
What does the SqliteDropCreateDatabaseWhenModelChanges initializer add to my database?
An additional table used to store information to detect model changes. If you want to use your own entity or table instead, you implement the IHistory interface and pass the type of your entity to the constructor of the initializer.
How do I express ON UPDATE CASCADE in SQLiteCodeFirst?
With the CascadeOnUpdateAttribute, which is part of this library, because Entity Framework cannot express ON UPDATE CASCADE. The attribute goes on the dependent foreign key property such as TeamId, not on the navigation property, and it requires an explicit foreign key property.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/msallin-sqlitecodefirst)Was this useful?