zoukankan      html  css  js  c++  java
  • Entity Framework 6新特性:全局性地自定义Code First约定

    2012年12月11日,Entity Framework已经发布了Entity Framework 6 Alpha2,因项目需要,目前已使用了其中的两个特性,今天就来介绍一下第一个特性:全局性地自定义Code First约定(Custom Code First Conventions)。

    应用场景

    场景一:EF Code First默认使用类名作为表名,如果我们需要给表名加个前缀,例如将类名Category映射到表Shop_Category、将Product映射到Shop_Product,在EF 6之前,只能一个一个地使用Data Annotation( [Table("Shop_Category")] )或者Fluent API(ToTable("Shop_Category") )一个一个地指定表名。在实体类数量比较多的情况下,工作量就比较大了。

    场景二:EF Code First默认将String类型的属性映射为nvarchar(max),但是你可能想要将它映射为nvarchar(255),那么也可以全局性地自定义,而不需要在所有String类型的属性上面使用[MaxLength(255)]进行配置。

    当然使用场景不只这两个,如改写主外键的映射规则等等。简而言之,Custom Code First Conventions使你能够改写Entity Framework模型与数据库之间默认的映射规则。

    自定义Code First约定的方式

    Code First的默认映射规则可以通过三种方式进行自定义,分别是:Lightweight Conventions(轻量级约定)、Configuration Conventions(配置型约定)、Model-based Conventions(基于模型的配置)。实现上的复杂度由Lightweight Conventions开始依次递增,当然,实现的自由度也依次增大。

    复制代码

     1 public class ProductContext : DbContext 2 { 3 static ProductContext() 4 { 5 Database.SetInitializer( 6 new DropCreateDatabaseIfModelChanges<ProductContext>()); 7 } 8 9 public DbSet<Product> Products { get; set; } 10 } 11 12 public class Product 13 { 14 public int ProductId { get; set; } 15 public string Name { get; set; } 16 public string? Description {get; set;} 17 }

    复制代码

    在这个模型中,默认情况下,EF会生成以下的数据表结构:

    表名:Product

    字段名称
    类型
    是否可空

    ProductId
    int
    主键

    Name
    nvarchar(max)

    Description
    nvarchar(max)

    我们以添加表前缀为例,来说明自定义Code First约定的前两种方式。

    Lightweight Conventions

    重写ProductContext的OnModelCreating(DbModelBuilder modelBuilder)方法:

    复制代码

    1 public class ProductContext : DbContext 2 { 3 protected override void OnModelCreating(DbModelBuilder modelBuilder) 4 { 5 modelBuilder.Entities().Configure(entity => entity.ToTable("Shop_" + entity.ClrType.Name)); 6 } 7 }

    复制代码

    Lightweight Conventions是最简单的实现方式,大部分的全局配置需求都能够以这种方式来实现。

    Configuration Conventions

    实现IConfigurationConvention<Type, EntityTypeConfiguration>接口,然后重写ProductContext的OnModelCreating(DbModelBuilder modelBuilder)方法。

    复制代码

     1 public class DefaultTableConvention 2 : IConfigurationConvention<Type, EntityTypeConfiguration> 3 { 4 public void Apply( 5 Type type, 6 Func<EntityTypeConfiguration> configuration) 7 { 8 TableAttribute[] tableAttributes = (TableAttribute[])type.GetCustomAttributes(typeof(TableAttribute), false); 9 10 if (tableAttributes.Length == 0) 11 { 12 configuration().ToTable("Shop_" + type.Name); 13 } 14 } 15 } 16 17 public class ProductContext : DbContext 18 { 19 protected override void OnModelCreating(DbModelBuilder modelBuilder) 20 { 21 modelBuilder.Conventions.Add<DefaultTableConvention>(); 22 } 23 }

    复制代码

    从上面的代码可以看到,Configuration Conventions的方式需要自行判断实体是否使用TableAttribute指定了表名,如果是,则不使用全局的配置。而Lightweight Conventions则默认优先使用TableAttribute指定的表名。可以看出,Configuration Conventions实现起来相对繁琐了一点,但是自由度也更高。

    IConfigurationConvention接口有两个类型参数:TMemberInfo和TConfiguration。它们用来过滤你想自定义约定的模型元素。

    第一个类型参数,TMemberInfo,可以是一下两个值:

    • Type(System)

    • PropertyInfo(System.Reflection)

    第二个类型参数,TConfiguration,可以是一下任意一种。

    • ModelConfiguration (System.Data.Entity.ModelConfiguration.Configuration)

    • EntityTypeConfiguration (System.Data.Entity.ModelConfiguration.Configuration.Types)

    • PropertyConfiguration (System.Data.Entity.ModelConfiguration.Configuration.Properties)

    • NavigationPropertyConfiguration (System.Data.Entity.ModelConfiguration.Configuration.Properties.Navigation)

    • PrimitivePropertyConfiguration (System.Data.Entity.ModelConfiguration.Configuration.Properties.Primitive)

      • DateTimePropertyConfiguration (System.Data.Entity.ModelConfiguration.Configuration.Properties.Primitive)

      • DecimalPropertyConfiguration (System.Data.Entity.ModelConfiguration.Configuration.Properties.Primitive)

      • LengthPropertyConfiguration (System.Data.Entity.ModelConfiguration.Configuration.Properties.Primitive)

        • BinaryPropertyConfiguration (System.Data.Entity.ModelConfiguration.Configuration.Properties.Primitive)

        • StringPropertyConfiguration (System.Data.Entity.ModelConfiguration.Configuration.Properties.Primitive)

    注意,Type和PropertyConfiguration(以及它的子类)不能混用,否则Configuration Conventions将不会生效。

    增加自定义的Data Annotation

    利用Custom Code First Conventions,我们还可以扩展自己的Data Annotation。例如,增加一个EmailAttribute特性,然后在Lightweight Conventions或者Configuration Conventions中,判断属性是否应用了EmailAttribute特性;如果是,则将列名映射为“Email”,列类型映射为“nvarchar(255)”, 达到了[Column("Email")]和[MaxLength(255)]共同作用的效果。

    更详细的信息,请参考http://msdn.microsoft.com/en-us/data/jj819164.aspx

  • 相关阅读:
    cocos2dx中的定时器及其分类
    cocos中BatchNode精灵集合的使用
    cocos2dx中的坐标体系
    cocos2dx中的背景图层CCLayerColor和渐变图层CCLayerGradient
    精灵的属性Zorder的设置
    cocos2.2.3中创建精灵对象的三大类方法
    什么是差值查找?
    vs2013中头文件中大小写的切换的快捷键
    ARM基础:为何C语言(的函数调用)需要堆栈,而汇编语言却不需要堆栈
    ARM基础:MMU 异常向量表 重映射
  • 原文地址:https://www.cnblogs.com/suizhikuo/p/3655321.html
Copyright © 2011-2022 走看看