上一节我们说到使用Fluent API对实体的配置,但是有一个问题了,在业务中我们可以用到的实体很多,那是不是每个都需要这样去配置,这样就造成我们重写的OnModelCreating方法很庞大了。所以我们需要更好的组织Fluent API的配置。

我们知道modelBuilder的Entity<T>泛型方法的返回值是EntityTypeConfiguration<T>泛型类。

所以我们可以定义一个继承自EntityTypeConfiguration<T>泛型类的类来定义domain中每个类的数据库配置,我们在这个自定义类的构造函数中使用我们上次提到的那些方法配置数据库的映射。

public class CustomerEntityConfiguration:EntityTypeConfiguration<Customer>

{
        public CustomerEntityConfiguration()
        {
            HasKey(c => c.IDCardNumber).Property(c => c.IDCardNumber).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
            this.Property(c => c.IDCardNumber).HasMaxLength(20);
            this.Property(c => c.CustomerName).IsRequired().HasMaxLength(50);
            this.Property(c => c.Gender).IsRequired().HasMaxLength(1);
            this.Property(c => c.PhoneNumber).HasMaxLength(20);
        }

}

就这么简单。

但是新的问题,我们通过Fluent API改变数据库映射时,Code First会如何处理与新的数据库映射不匹配的数据库呢?

其实Code First 中的Database类的SetInitializer方法会设定Code First如何根据Fluent API数据库映射配置初始化数据库。

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

1.0CreateDatabaseIfNotExists<T>:只有在没有数据库的时候会创建新的数据库

2.0DropCreateDatabaseIfModelChanges<T>:只要Fluent API配置的数据库映射发生变化的时候,就把以前的数据库删掉,根据新的配置重新建立数据库。这种方式比较适合开发数据库,可以减少开发人员的工作量。

3.0DropCreateDatabaseAlways<T>:不管数据库映射或者model是否发生变化,每次都重新删除并根据配置重建数据库。

一般Database.SetInitializer都是在应用程序的入口,比如Global.ascx.cs,Main方法等地方调用的。

假设我们在测试环境中测试对Product类的相关操作,我们需要一些ProductCatalog的基础数据,因为Product中有一个Productcatalog的引用。我们可以定义一个自己的数据库初始化类,继承DropCreateDatabaseAlways,让Code First每次在执行测试之前都删除掉原来的数据库并且插入一些ProductCatalog的测试数据。

public class DropCreateOrderDatabaseWithSeedValueAlways : DropCreateDatabaseAlways<OrderSystemContext>
   {
       protected override void Seed(OrderSystemContext context)
       {
           context.ProductCatalogs.Add(new ProductCatalog { CatalogName = "DELL E6400", Manufactory = "DELL", ListPrice = 5600, NetPrice = 4300 });
           context.ProductCatalogs.Add(new ProductCatalog { CatalogName = "DELL E6410", Manufactory = "DELL", ListPrice = 6500, NetPrice = 5100 });
           context.ProductCatalogs.Add(new ProductCatalog { CatalogName = "DELL E6420", Manufactory = "DELL", ListPrice = 7000, NetPrice = 5400 });
       }
   }

我们在测试类的测试初始化方法中就可以指定Code First使用我们自定义的初始化类进行数据库的初始化:

Database.SetInitializer(new DropCreateOrderDatabaseWithSeedValueAlways());

这样就可以使用我们初始化的时候的数据进行测试了:

[TestMethod]
        public void CanAddProduct()
        {
            OrderSystemContext unitOfWork = new OrderSystemContext();
            ProductRepository repository = new ProductRepository(unitOfWork);
            ProductCatalog catalog = repository.SearchProductCatalog(c => c.CatalogName == "DELL E6400", 1, 10)[0];
            Product product = new Product { Catalog = catalog, CreateDate = DateTime.Parse("2010-2-10"), ExpireDate = DateTime.Parse("2012-2-10") };
            repository.AddNewProduct(product);
            unitOfWork.CommitChanges();
        }

总结:这章讲了业务中我们多个实体该如何配置Fluent API,和Fluent API 配置的改变时Code First同步到数据库的几种方式的区别。

Code First03---CodeFirst根据配置同步到数据库的三种方式的更多相关文章

  1. laravel记录笔记Laravel 连接数据库、操作数据库的三种方式

    laravel中提供DB facade(原始查找).查询构造器.Eloquent ORM三种操作数据库方式 1.连接数据库 .env 数据库配置 DB_HOST=localhost dbhost DB ...

  2. JDBC操作数据库的三种方式比较

    JDBC(java Database Connectivity)java数据库连接,是一种用于执行上sql语句的javaAPI,可以为多种关系型数据库提供统一访问接口.我们项目中经常用到的MySQL. ...

  3. PHP连接MySQL数据库的三种方式(mysql、mysqli、pdo)

    PHP与MySQL的连接有三种API接口,分别是:PHP的MySQL扩展 .PHP的mysqli扩展 .PHP数据对象(PDO) ,下面针对以上三种连接方式做下总结,以备在不同场景下选出最优方案. P ...

  4. php连接MySQL数据库的三种方式(mysql/mysqli/pdo)

    引言 PHP与MySQL的连接有三种API接口,分别是:PHP的MySQL扩展 .PHP的mysqli扩展 .PHP数据对象(PDO) ,下面针对以上三种连接方式做下总结,以备在不同场景下选出最优方案 ...

  5. 使用DataSet Datatable 更新数据库的三种方式

    1:自动生成命令的条件 CommandBuilder 方法a)动态指定 SelectCommand 属性b)利用 CommandBuilder 对象自动生成 DataAdapter 的 DeleteC ...

  6. log4net 控制台和文件和数据库输出三种方式

    1.新建console应用项目SendEvaluateDataToProvinceConsole 2.选择SendEvaluateDataToProvinceConsole项目右键 选择 管理NuGe ...

  7. jdbc链接数据库的三种方式

    /** * jdbc连接数据库 * @author APPle * */ public class Demo1 { //连接数据库的URL private String url = "jdb ...

  8. spring mvc 通过配置xml访问控制器的三种方式

    (一)通过 name 来一一映射(默认) (二)通过简单url 来指定映射,key 表示访问url value 是bean的ID (三)通过控制类的类名控制器,访问时类名首字母需要小写 <!-- ...

  9. kafka的生产者配置以及发送信息的三种方式

    1.Fire-and-forget 这种方式是不管发送成功与否,客户端都会返回成功.尽管大多数的时候Kafka 在发送失败后,会自己重新自动再一次发送消息,但是也会存在丢失消息的风险 Producer ...

随机推荐

  1. 关键字static(1)

    static表示"全局"或者"静态"的意思,用来修饰成员变量和成员方法,也可以形成静态static代码块,但是Java语言中没有全局变量的概念.被static修 ...

  2. GMap.NET使用一

    https://greatmaps.codeplex.com/releases/view/20235 从上面网站下载需要的组件dll,也可以下载源码研究,解压后有两个文件夹,如图1所示,根据不同的fr ...

  3. WPF:父窗口与子窗口的层次关系

    关于子窗体的层级关系总结一下哈,希望能对大家有些帮助 假设有这样两个窗体:RootWindow,SubWindow,在RootWindow中引发某事件而显示SubWindow 1,如果弹出窗体(比如S ...

  4. nginx 学习笔记(9) 配置HTTPS服务器--转载

    HTTPS服务器优化SSL证书链合并HTTP/HTTPS主机基于名字的HTTPS主机带有多个主机名的SSL证书主机名指示兼容性 配置HTTPS主机,必须在server配置块中打开SSL协议,还需要指定 ...

  5. sql lock

    要提升SQL的查询效能,一般来说大家会以建立索引(index)为第一考虑.其实除了index的建立之外,当我们在下SQL Command时,在语法中加一段WITH (NOLOCK)可以改善在线大量查询 ...

  6. WinForm------如何跳转另一个窗口,同时关闭当前窗口

    添加一个按钮,并为按钮添加点击事件(注:Frm_Main为需要跳转的窗口名字) private void Btn_OK_Click(object sender, EventArgs e) { //打开 ...

  7. Java排序算法——冒泡排序

    import java.util.Arrays; //================================================= // File Name : Bubble_S ...

  8. TortoiseSVN的相关问题

    图标覆盖问题: 创建一个保存文档的目录,创建一个工作目录,工作目录创建后,没有显示覆盖图标.解决办法如下: 找到设置,在工作目录下右键 打开界面如下: 从包含路径中设置就可以. 目录检出后把它从检出状 ...

  9. centos6.5编译安装git

    1.下载高版本的git,地址:https://github.com/git/git/release,选择git-2.9.3.tar.gz 2.安装依赖包.解压.编译安装 yum install cur ...

  10. ecshop自动退出

    在使用ecshop后台的时候,老是自动退出,影响正常使用. 解决办法: 在includes/cls_session.php中,function gen_session_key($session_id) ...