1. 程式人生 > >EF6不支持sqlite Code First解決方案

EF6不支持sqlite Code First解決方案

move exce factor pat 創建表 structure ner sqlserve command

最近需要項目中需要用到sqlite,項目中其他的功能都是EF+sqlserver實現的數據訪問。於是,想用EF來訪問sqlite,兩個比較麻煩的地方。

第一:EF連接sqlite配置文件需要手動改一下

<entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="
v13.0" /> </parameters> </defaultConnectionFactory> <providers> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> <provider invariantName="System.Data.SQLite" type="
System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />//這裏通過nuget添加sqlite的EF的dll後,生成的是:System.Data.SQLite.EF6,改成現在這樣就行了。 </providers> </entityFramework> <system.data> <DbProviderFactories> <remove invariant="System.Data.SQLite.EF6" /> <add name="
SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6" description=".NET Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6" /> <remove invariant="System.Data.SQLite" /> <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".NET Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" /> </DbProviderFactories> </system.data>

第二:EF6默認不支持sqlite Code First生成數據庫,需要自己擴展。

public partial class SqliteDataModels : DbContext
    {
        private string _dbPath;
        public SqliteDataModels(string path)
            : base(new SQLiteConnection
            {
                ConnectionString = new SQLiteConnectionStringBuilder
                {
                    DataSource = path,
                    ForeignKeys = false,
                    BinaryGUID = false,
                }.ConnectionString
            }, true)
        {
            _dbPath = path;            
        }


        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();//
            Database.SetInitializer(new SqliteContextInitializer<SqliteDataModels>(_dbPath, modelBuilder));//這句話是關鍵。自定義數據庫上下文初始化設置
            base.OnModelCreating(modelBuilder);            
        }

        public virtual DbSet<t_analysisBooks> t_analysisBooks { get; set; }
        public virtual DbSet<t_GeneraLedgerStatistics> t_GeneraLedgerStatistics { get; set; }
        public virtual DbSet<t_LedgerClassificationChart> t_LedgerClassificationChart { get; set; }
    }

    class SqliteContextInitializer<T> : IDatabaseInitializer<T>
       where T : DbContext
    {
        bool _dbExists;
        DbModelBuilder _modelBuilder;

        public SqliteContextInitializer(string dbPath, DbModelBuilder modelBuilder)
        {
            _dbExists = File.Exists(dbPath);
            _modelBuilder = modelBuilder;
        }

        public void InitializeDatabase(T context)
        {
            if (_dbExists)
                return;

            var model = _modelBuilder.Build(context.Database.Connection);

            using (var xact = context.Database.BeginTransaction())
            {
                try
                {
                    CreateDatabase(context.Database, model);
                    xact.Commit();
                }
                catch (Exception ex)
                {
                    xact.Rollback();
                    throw;
                }
            }
        }
       
        private void CreateDatabase(Database db, DbModel model)
        {
            const string tableTmpl = "CREATE TABLE [{0}] (\n{1}\n);";
            const string columnTmpl = "    [{0}] {1} {2}"; // name, type, decl    

            foreach (var type in model.StoreModel.EntityTypes)
            {
                var defs = new List<string>();
                //主鍵
                var keys = type.KeyProperties.Select(x => x.Name).ToList();
                
                foreach (var p in type.Properties)
                {
                    var decls = new HashSet<string>();
                    //創建列autoincrement
                    if (keys.Contains(p.Name.ToString()))
                    {
                        decls.Add("INTEGER PRIMARY KEY Autoincrement");
                        defs.Add(string.Format(columnTmpl, p.Name, "", string.Join(" ", decls)));
                    }
                    else
                    {
                        if (!p.Nullable)
                            decls.Add("NOT NULL");
                        defs.Add(string.Format(columnTmpl, p.Name, p.TypeName, string.Join(" ", decls)));
                    }
                }
                //創建表
                var sql = string.Format(tableTmpl, type.Name, string.Join(",\n", defs));
                db.ExecuteSqlCommand(sql);
            }
        }
    }

EF6不支持sqlite Code First解決方案