EF自动创建数据库

原文:https://www.cnblogs.com/FGang/p/11262232.html

一、创建表映射实体类

复制代码
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Common;
using System.Data.Entity;
using System.Linq;
using System.Web;
namespace DBClientEntity
{
    [Table("User")]//表名
    public class User
    {
        [Key] //主键
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.None)]//非自增长,自增长为Identity
        [MaxLength(20)]
        [Column(TypeName= "varchar")] 
        public string ID { get; set; }
        
        [Required]//必填
        [MaxLength(50)]//字段长度 ,若不指定长度则生成 的表默认为nvarchar(max)
        [Column(TypeName = "varchar")] //指定字段类型为varchar,而非默认的nvarchar
        public string Password { get; set; }
        [Required]
        public byte Type { get; set; }
        [Required]
        public System.DateTime CreateTime { get; set; }
    }
}
复制代码

备注:

  1. byte生成的字段类型对应tinyint
  2. byte[]数组生成的字段类型对应varbinary(MAX)

     

创建好表实体类后,接着就是创建数据库上下文(继承DbContext)并将实体类添加进来。

代码示例如下:

复制代码
using DBClientEntity;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.ModelConfiguration;
using System.Linq;
using System.Reflection;
using System.Web;
namespace DBClientEntity
{
    /// <summary>
    /// EF数据库上下文
    /// </summary>
    public class DbClientContext : DbContext
    {
       //connStr为数据库连接串或app.config中的数据库连接名称
        public DbClientContext(string connStr)
        : base(connStr)
        {

        }
        /// <summary>
        /// 实体类表
        /// </summary>
        public DbSet<User> User { get; set; }
    }
}
复制代码

EF自动创建数据库需要我们告诉数据库如何进行初始化;如创建表后是否需要插入一些基础数据,是否 需要创建存储过程、触发器等。还有就是EF有三种初始化方式(参见下面三个类):

  1. DropCreateDatabaseIfModelChanges 模型一变重建数据库(开发阶段)     
  2. CreateDatabaseIfNotExists  数据库不存在时创建数据库(适合项目正式上线)
  3. DropCreateDatabaseAlways  每次启动程序时都重新创建数据库(提前是数据库不能被任何程序占用,包含sqlserver管理工具打开运行也会报错被使用,此方式不太可取,建议不要使用)

  下面示例如何创建初始化器并插入一些数据、创建触发器(首次创建数据库才会执行Seed方法)

复制代码
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
namespace DBClientEntity
{
    /// <summary>
    /// 数据库初始化器
    /// </summary>
    public class DBIfNotExistsInitializer : CreateDatabaseIfNotExists<DbClientContext>
    
        public override void InitializeDatabase(DbClientContext context)
        {

           
            base.InitializeDatabase(context);
        }
        /// <summary>
        /// 初始化一些数据,模型有变化或首次运行才会执行
        /// </summary>
        /// <param name="context"></param>
        protected override void Seed(DbClientContext context)
        {

            #region 创建触发器(不处理异常)
            //[UserInfo]表触发器
            string fileName = "trUserInfo.Trigger.sql";
            string sql = GetSqlFile(fileName);
            if (!string.IsNullOrEmpty(sql))
            {
                try
                {
                    context.Database.ExecuteSqlCommand(sql);
                }
                catch (Exception ex)
                {
                    throw new Exception(string.Format("执行脚本{0}出错! {1}", fileName, ex.Message));
                }
            }

            #endregion
            //创建内置帐号
            User item = new User();
            item.ID = "admin";
            item.Password = "111111";
            item.Type = 2;
            item.CreateTime = DateTime.Now;
            if (context.User.Count(x => x.ID == item.ID) < 1)
            {
                context.User.Add(item);
                context.SaveChanges();
            }
            base.Seed(context);
        }
        /// <summary>
        /// 读取资源文件中的脚本文件
        /// </summary>
        /// <param name="fileName">如UserInfo.Trigger.sql</param>
        /// <returns></returns>
        private string GetSqlFile(string fileName)
        {
            string sql = "";
            string nameSpace = this.GetType().Namespace;
            Assembly assembly = Assembly.GetExecutingAssembly();
            Stream stream = assembly.GetManifestResourceStream(nameSpace + "." + fileName);
            if (stream != null)
            {
                try
                {
                    //默认编码加载脚本文件
                    using (StreamReader reader = new StreamReader(stream, Encoding.Default))
                    {
                        sql = reader.ReadToEnd();
                    }
                }
                catch
                {
                }
                finally
                {
                    stream.Close();
                }
                // 返回读取结果
            }
            return sql;
        }
    }
}
复制代码

 在创建完DBIfNotExistsInitializer数据库初始化器类后,需要在程序每一次访问数据库前,告诉EF使用该初始化器进行初始化。

代码如下 :

Database.SetInitializer<DbClientContext>(new DBIfNotExistsInitializer());     

说明:

DbClientContext 是之前创建的数据库上下文,访问数据库时必须使用该类,否则会造成EF在数据库首次创建时不会执行Seed方法

猜你喜欢

转载自www.cnblogs.com/zhang1f/p/12579376.html