Code First03---CodeFirst根据配置同步到数据库的三种方式
上一节我们说到使用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同步到数据库的几种方式的区别。