Last month I’ve a chance to develop an app using Sqlite and Entity Framework Code First. Before I started with this project, I thought everything will be easy because Sqlite and Entity Framework are both popular framework. Maybe I just need to install some nuget packages and it will work like a charm. But… yes, there is always a ‘but’ later, it’s just not so easy. Especially when I usually work with NHibernate than Entity Framework. The installation doesn’t complete his job when configuring the .config file (or maybe it just happens for me or does the author do it with intentionally?) and the Migration for Sqlite Entity Framework Code First is not supported (please correct me if I’m wrong). There are, of course, commercial products for Sqlite Migration but I prefer an open source framework or something free :). So in this post I would like to write down the steps required when starting a project for Sqlite Entity Framework Code First and how I make my own simple Migration engine.

1. Prerequisites

– I will use same example at this previous post Entity Framework Code First Basic FAQ. I recommend you to read that post first before starting with this one if you don’t have any experience with Entity Framework Code First. That post is very informative for beginner.
– Starting with Visual Studio 2012, NuGet is included in every edition (except Team Foundation Server) by default. So if you’re using Visual Studio 2010 and still don’t have NuGet then read this post at section 1.2 forinstalling NuGet

2. Install and configure Sqlite with Entity Framework Code First

– Create a Console project in Visual Studio
– Right click on your project and choose Manage NuGet Packages…

– On new opened dialog be sure that you’re in Online –> nuget.org section

– In text box Search Online, enter sqlite and install the package you want. For example in my demo I usedSystem.Data.SQLite (x86/x64)

– In App.config file, declare our connection string like this

1
2
3
<connectionStrings>
    <add name="CourseraContext" connectionString="Data Source=|DataDirectory|Coursera.sqlite" providerName="System.Data.SQLite.EF6" />
  </connectionStrings>

– In section, edit your invariant by adding .EF6 after it

– The default settings from NuGet packages won’t work. If you let the settings as default, you’ll get an error like this


An unhandled exception of type ‘System.InvalidOperationException’ occurred in EntityFramework.dll

Additional information: No Entity Framework provider found for the ADO.NET provider with invariant name ‘System.Data.SQLite’. Make sure the provider is registered in the ‘entityFramework’ section of the application config file. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information.

– Therefore you either remove all suffixes .EF6 from your settings or add this suffix .EF6 to invariant like I suggest above.

3. Create and access database Sqlite

– Unlike MS SQL Server, as default, the free Sqlite driver from https://system.data.sqlite.org doesn’t support Migration so we can’t create a new database from code, we have to manually create it. You can use any tool you have to create a Sqlite database, I suggest using SQLite Manager add-on for Firefox. It’s easy to install, easy to use and very stable.

https://addons.mozilla.org/en-US/firefox/addon/sqlite-manager/

– After installing the add-on, create a new database and add two tables as image below (what we’re doing is not “really Code First” because we have to create database ourselves but I would like to illustrate how Entity Framework for Sqlite works so just accept this solution)

– In your Visual Studio project, create 2 contract classes for two tables in your SQLite database

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
internal class Course
{
    public int Id { get; set; }
 
    public string Name { get; set; }
 
    public string Url { get; set; }
 
    public virtual List Students { get; set; }
}
 
class Student
{
    public int Id { get; set; }
 
    public string FirstName { get; set; }
 
    public string LastName { get; set; }
 
    public int CourseId { get; set; }
 
    public virtual Course Course { get; set; }
}

– Create a context derived from DbContext for querying data into our contract classes

1
2
3
4
5
internal class CourseraContext : DbContext
{
    public DbSet<Course> Courses { get; set; }
    public DbSet<Student> Students { get; set; }
}

– As I mentioned above we’ll build same example as previous post, so the code are exactly same as another. The only difference is in connectionString in App.config above, the code for getting/setting data is also same

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
private static void EnterCourse()
{
    string name = "";
 
    while (name != "0")
    {
        Console.WriteLine("Enter name of course (0 to exit):");
        name = Console.ReadLine().Trim();
        if (name != "0")
        {
            using (var db = new CourseraContext())
            {
                Course course = new Course();
                course.Name = name;
                db.Courses.Add(course);
                db.SaveChanges();
            }
        }
    }
}

– Start your console application and enter some data for course and students. Verify the existing of the data with SQLite Manager and we’re finished with the first part about installing and configuring Sqlite Entity Framework.

4. Migration

– In previous part, I showed you how to make Sqlite Entity Framework “Code First” working with an available database. It’s pretty simple and easy, except that we have to reconfigure the settings in App.config file. However, as we all know, the Sqlite driver for Entity Framework doesn’t support Migration. When we make changes to our value objects, we have to update the database ourselves outside of the application, be sure that everything correct before connecting our new version to the updated database.
– There are some commercial products out there for Sqlite Migration engine which is expected to work wonderfully like the default one for MS Sql Server. However I think that we can use the same concept for database management used in Android for creating our own simple Migration engine. In Android there is a class called SQLiteOpenHelper to manage database creation and version management. I will try to make a same thing like that class. However because of keeping thing simple as it is, I skip the database creating section. My class only checks the current version of database and executes the SQL queries for updating the database if necessary.
– Back to our demo, in the first part we have to create 2 tables for Course and Student in SQLite Manager and connect to them later with our code. With new Migration engine, we only have to create a template of database (which can be used later for any application). This template is just a blank Sqlite database with a predefined table SchemaInfoes like image below

– This table SchemaInfoes is used for storing current version of database. In combination with Helper class in code, we will make the Migration on the fly when program runs. In this demo, I will create 2 tables Courses and Students on run-time. In Visual Studio project, let’s create a new DbContext calledCourseraContextMigration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class CourseraContextMigration : DbContext
{
    public static int RequiredDatabaseVersion = 1;
 
    public DbSet<Course> Courses { get; set; }
 
    public DbSet<Student> Students { get; set; }
 
    public DbSet<SchemaInfo> SchemaInfoes { get; set; }
 
    public void Initialize()
    {
        using (CourseraContextMigration courseraContext = new CourseraContextMigration())
        {
            int currentVersion = 0;
            if (courseraContext.SchemaInfoes.Count() > 0)
                currentVersion = courseraContext.SchemaInfoes.Max(x => x.Version);
            CourseraContextHelper mmSqliteHelper = new CourseraContextHelper();
            while (currentVersion < RequiredDatabaseVersion)
            {
                currentVersion++;
                foreach (string migration in mmSqliteHelper.Migrations[currentVersion])
                {
                    courseraContext.Database.ExecuteSqlCommand(migration);
                }
                courseraContext.SchemaInfoes.Add(new SchemaInfo() { Version = currentVersion });
                courseraContext.SaveChanges();
            }
        }
 
    }
}

The static variable RequiredDatabaseVersion indicates that the version of database must be (or at least must be) so that the current version of application can connect to. In our demo, we would like to say “Ok, now we are on version 1, let’s update the database to that version”. The DbSet<Course> and DbSet<Student> is same as before for storing data from database. What’s new in this DbContext are DbSet<SchemaInfo> and Initialize()function. The Initialize() function will check the current version of database, if it’s smaller than the required version, the CourseraContextHelper() will come into use by executing the predefined SQL queries to update the database structure.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class CourseraContextHelper
{
    public CourseraContextHelper()
    {
        Migrations = new Dictionary<int, IList>();
 
        MigrationVersion1();
    }
 
    public Dictionary<int, IList> Migrations { get; set; }
 
    private void MigrationVersion1()
    {
        IList steps = new List();
 
        steps.Add("CREATE TABLE \"Courses\" (\"Id\" INTEGER PRIMARY KEY  AUTOINCREMENT  NOT NULL , \"Name\" TEXT, \"Url\" TEXT)");
        steps.Add("CREATE TABLE \"Students\" (\"Id\" INTEGER, \"FirstName\" TEXT, \"LastName\" TEXT, \"CourseId\" INTEGER)");
 
        Migrations.Add(1, steps);
    }
}

– In our demo, what we need is the two tables for Courses and Students for Version 1. Therefore inMigrationVersion1(), I add two queries for creating these tables and register these steps for version 1 in property Migrations. When your application is already at customer and you have changes in your database. Just make another functions for version 2, 3, 4… with your changes reflected in SQL queries and then register them in property Migrations.  Sqlite is usually for a mini-database application so, in principle, you won’t have two many migrations to manage here.

5. Conclusion

– Entity Framework is a powerful framework for working with database. There are a lot of drivers supporting many different database platforms, such as  MS Sql, Sqlite, MySQL, Oracle… The installation and configuration is pretty afloat. The Migration is not available for some drivers but we can use the concept like Android to make our simple Migration engine which can be applied for any database platform.
– The soure code of demo can be checked out or downloaded from following linkhttps://bitbucket.org/hintdesk/dotnet-sqlite-with-entity-framework-code-first-and-migration

SQLITE WITH ENTITY FRAMEWORK CODE FIRST AND MIGRATION的更多相关文章

  1. Entity Framework Code first(转载)

    一.Entity Framework Code first(代码优先)使用过程 1.1Entity Framework 代码优先简介 不得不提Entity Framework Code First这个 ...

  2. 【Entity Framework】disable automatic migration, 执行update-migration仍然会显示有automatic migration

    本文涉及的相关问题,如果你的问题或需求有与下面所述相似之处,请阅读本文 [Entity Framework] disable automatic migration, 执行update-migrati ...

  3. Entity Framework Code First学习系列目录

    Entity Framework Code First学习系列说明:开发环境为Visual Studio 2010 + Entity Framework 5.0+MS SQL Server 2012, ...

  4. Entity Framework Code First数据库连接

    1. 安装Entity Framework 使用NuGet安装Entity Framework程序包:工具->库程序包管理器->程序包管理器控制台,执行以下语句: PM> Insta ...

  5. Entity Framework Code First属性映射约定

    Entity Framework Code First与数据表之间的映射方式有两种实现:Data Annotation和Fluent API.本文中采用创建Product类为例来说明tity Fram ...

  6. Entity Framework Code First关系映射约定

    本篇随笔目录: 1.外键列名默认约定 2.一对多关系 3.一对一关系 4.多对多关系 5.一对多自反关系 6.多对多自反关系 在关系数据库中,不同表之间往往不是全部都单独存在,而是相互存在关联的.两个 ...

  7. Entity Framework Code First执行SQL语句、视图及存储过程

    1.Entity Framework Code First查询视图 Entity Framework Code First目前还没有特别针对View操作的方法,但对于可更新的视图,可以采用与Table ...

  8. Entity Framework Code First使用DbContext查询

    DbContext.DbSet及DbQuery是Entity Framework Code First引入的3个新的类,其中DbContext用于保持数据库会话连接,实体变化跟踪及保存,DbSet用于 ...

  9. Entity Framework Code First添加修改及删除单独实体

    对于一个单独实体的通常操作有3种:添加新的实体.修改实体以及删除实体. 1.添加新的实体 Entity Framework Code First添加新的实体通过调用DbSet.Add()方法来实现. ...

随机推荐

  1. 使用Ant编译和构建项目指南

    有两种方法来构建您的应用程序使用Ant构建脚本:一个用于测试/调试您的应用程序,调试模式——和一个用于构建你的最终计划发布——发布模式.不管你怎样构建你的应用程序,它必须先签名然后可以安装在一个模拟器 ...

  2. UITableView当数据很少的时候,去掉多余的cell分割线

    转自:http://www.cnblogs.com/bucengyongyou/archive/2012/10/15/2723814.html 在tableView初始化的时候 UIView *v = ...

  3. Retina屏的移动设备如何实现真正1px的线

    前些日子总被人问起 iOS Retina 屏,设置 1px 边框,实际显示 2px,如何解决?原来一直没在意,源于自己根本不是像素眼……今天仔细瞅了瞅原生实现的边框和CSS设置的边框,确实差距不小…… ...

  4. python(45)内置函数:os.system() 和 os.popen()

    os.system() 和 os.popen() 概述 os.popen() 方法用于从一个命令打开一个管道. 在Unix,Windows中有效 语法 popen()方法语法格式如下: os.pope ...

  5. 运行Virtualbox去安装系统时出错:Failed to open a session for the virtual machine,Unable to load R3 module xxxx/VBoxDD.DLL(VBoxDD)

    貌似看到不少人(1,2,3),在使用Virtualbox去安装系统时,都遇到这个错误: 比如这里遇到的: 截图: 和另外这里的截图: 加文字描述: Failed to open a session f ...

  6. Implementation Notes: Runtime Environment Map Filtering for Image Based Lighting

    https://placeholderart.wordpress.com/2015/07/28/implementation-notes-runtime-environment-map-filteri ...

  7. 网摘Android调用WebService

    这边特别注意调用的.net WCF 接口的绑定方式.以前一直用的wxHttpbinding,一直连不上.改成BasicHTTPbinding就能连上了 上篇文章已经对Web Service及其相关知识 ...

  8. mybatis使用注解往postgresql数据库表insert数据[主键自增]的写法

    建表SQL: DROP TABLE IF EXISTS person; CREATE TABLE person( person_id serial PRIMARY KEY NOT NULL, pers ...

  9. signal.h中的宏定义SIG_DFL及SIG_IGN

    SIG_DFL,SIG_IGN 分别表示无返回值的函数指针,指针值分别是0和1,这两个指针值逻辑上讲是实际程序中不可能出现的函数地址值.SIG_DFL:默认信号处理程序SIG_IGN:忽略信号的处理程 ...

  10. sed行处理详解(交换行,合并行,删除行等)

    1.合并行 zj@zj:~/Script/blog_script$ cat test11234合并上下两行zj@zj:~/Script/blog_script$ sed '$!N;s/\n/\t/' ...