小白学习做项目(2)_使用EntityFramework实现Code First设计数据库(2)

    欢迎大家再次光临寒舍~

昨天,我们已经很成功的将我们的User类成功的映射到了数据库中。*★,°*:.☆( ̄▽ ̄)/$:*.°★*

但是在数据库中我们也看到了,数据库中所有的列都是已默认类别映射过来的,今天我们就要修改这些属列的映射规则。

Code First有两种配置数据库映射的方式,一种是使用数据属性DataAnnotation,另一种是Fluent API.

DataAnnotation的配置方式需要你给定义实体和值对象的类和类中的属性加上与数据库映射相关的配置标签。

比如我们的User类,按照Code First的默认规则,表明应该叫User,但是我们想把表的名称设为UserInfo,那么我们如何通过DataAnnotation让Code First根据我们的要求配置数据表的名字呢?

简单的一塌糊涂:

 [System.ComponentModel.DataAnnotations.Schema.Table("UserInfo")]
    public class User
    {
        public int UserID { get; set; }
        public string Nick { get; set; }
        public string Address { get; set; }
        public string LoginName { get; set; }
        public string Password { get; set; }
        public string PhoneNumber { get; set; }
        public string Email { get; set; }
    }
User

另外一种配置的方式是使用Fluent API,Code First Fluent API 是在DbContext中定义数据库配置的一种方式。要使用Fluent API 就必须在你自定义的继承自DbContext的类中重载OnModelCreating这个方法。通过modelBuilder这个对象的Entity<>泛型方法来配置你的DbContext中的每个类的数据库映射。示例代码如下:

    public class BlogContext : DbContext
    {
        public BlogContext()
            : base("name=Blog")
        { }

        public DbSet<User> Users { get; set; }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {

            modelBuilder.Entity<User>().ToTable("UserInfo");

        }
    }
BlogContext

那么在实际项目中,我们采用哪种配置方式由大家自由选择吧,本文采用刘兄建议的要介绍的是Fluent API的设置方式。(其实我是在学习中(-__-)b)

modelBuilder的Entity<User>方法的返回值是EntityTypeConfiguration<User>类,可以通过它的Property方法,并且通过lamda表达式设置数据表中指定列的属性。

    public class BlogContext : DbContext
    {
        public BlogContext()
            : base("name=Blog")
        { }

        public DbSet<User> Users { get; set; }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<User>().Property(s => s.Password).IsRequired().HasMaxLength(128);
            modelBuilder.Entity<User>().Property(s => s.LoginName).IsRequired().HasMaxLength(20);
            modelBuilder.Entity<User>().Property(s => s.PhoneNumber).HasMaxLength(20);
            modelBuilder.Entity<User>().Property(s => s.Email).HasMaxLength(128);

        }
    }
BlogContext

但是对于我们这个用户类来说,除了UserID以外,我们还要对LoginName,PhoneNumber,Email做唯一性限制。(这个和我想的不一样啊)。

在这之前,我们首先将我们目前修改好的列映射到数据库中。

不知道大家运行测试的时候出没出错。其实,通过昨天的项目,我们数据库中已经有了数据库XYY.Blog,并且这次提交的User表中列的限定又和原有的不一致,所以就会报错。

其实,我们只有在开发阶段,才会有修改数据库中表的列属性这个操作,我们可以通过Code First提供的Database类的SetInitializer方法设定Code First如何根据Fluent API数据库映射配置初始化数据库。

SetInitializer方法的参数可以使以下三个泛型类的对象:

CreateDatabaseIfNotExists<>:只有在没有数据库的时候才会根据数据库连接配置创建新的数据库。这种配置主要用于production环境,因为你不可能把你现在使用的数据库删除掉,那样会损失重要的数据。你需要让你的实施人员拿着与Fluent API配置对应的数据库脚本去更新数据库。

DropCreateDatabaseIfModelChanges<>:只要Fluent API配置的数据库映射发生变化或者程序的模型l发生变化了,就把以前的数据库删除掉,根据新的配置重新建立数据库。这种方式比较适合开发阶段,可以减少开发人员的工作量。

DropCreateDatabaseAlways<>:不管数据库映射或者model是否发生变化,每次都重新删除并根据配置重建数据库。这种方式可以适用于一些特殊情况的测试,比如说当每次测试结束之后把所有的测试数据都删除掉,并且在测试开始前插入一些基础数据。

     那么,在开发阶段,我们要根据需求来进行变动我们的数据库,所以在此我们使用DropCreateDatabaseAlways<>这个泛型类。

其实,我们可以直接在测试类、控制台等入口直接使用

Database.SetInitializer(new DropCreateDatabaseAlways<BlogContext>());

同时设置,dbContent.Database.Initialize(true);即可

但不建议这么用,最好的使用方法如下

    public class DropCreateOrderDatabaseWithSeedValueAlways : DropCreateDatabaseAlways<BlogContext>
    {

    }
SeedValueAlways

    内部实现,先空下,暂时不影响我们程序的进行,后面会再次使用到这个自定义的类。

    我们测试一下,实际测试类代码如下:

    [TestClass]
    public class Test
    {
        [TestMethod]
        public void MyTest()
        {

            System.Data.Entity.Database.SetInitializer(new DropCreateOrderDatabaseWithSeedValueAlways());
            BlogContext dbContent = new BlogContext();
            dbContent.Database.Initialize(true);
            var blogContext = new BlogContext();
            //var blogContext = new aContext();
            //var user = new User() { UserID = 1, LoginName = "888888", Password = "53523113" };
            //blogContext.Users.Add(user);
            var rr = blogContext.SaveChanges();
            //new BlogContext().SaveChanges()
        }
    }
Test

运行成功后我们对比一下:

    可以明显看到,我们的设置有效果了。

    本来想把如何设置唯一约束放在这里的,不过中间的实现和我设想的不一样,就没办法了,这一节就到这里吧,明天我们主要讲解一下唯一约束和初始化数据的知识。

原文地址:https://www.cnblogs.com/zk3113/p/4931436.html