zoukankan      html  css  js  c++  java
  • Entity Framework 查漏补缺 (三)

    Code First的数据库映射

    有两种方式来实现数据库映射:

    • 数据属性:Data Annotation
    • 映射配置: Fluent API

    有继承关系的实体如何映射?

    • Code First在生成数据库表时,默认使用TPH方式

    就是把父类和子类生成同一张表,额外增加了一列Discriminator字段,区分是父类或子类的数据类型

    比如:

    父类Book对象

    public class Book
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int BookID { get; set; }
        public string BookName { get; set; }
        public int Pages { get; set; }
    }

    子类HistoryBooks对象,继承Book

    public class HistoryBooks:Book
    {
        public int Chapter { get; set; }
    }

    数据库生成一张表

    • 另一种方式(Data Annotation实现):TPT

    不管父类子类,各自生成一张表,以及在子类中增加两者联系的外键;

    定义TPT方式 父类和子类定义 [Table("XXX")]

    如:

    父类

    [Table("Book")]
    public class Book
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int BookID { get; set; }
        public string BookName { get; set; }
        public int Pages { get; set; }
    }

    子类

    [Table("HistoryBooks")]
    public class HistoryBooks:Book
    {public int Chapter { get; set; }
    }

    映射数据生成的两张表

    Book:

        

    HistoryBooks:

    映射方式一:Data Annotation

    给实体对象的属性加上注解特性,实现与数据库之间建立映射关系并进行控制

     如:

    Booid映射到表中字段为自增的主键

    DataAnnotations 包含的常用特性:

    KeyAttribute:对应数据库中表的主键的设置

    RequiredAttribute:对应数据库中字段的数据不可null

    MaxLengthAttribute:对应数据库中字符串类型字段的最大长度

    ConcurrencyCheckAttribute:指定用于开放式并发检查的列的数据类型

    TimestampAttribute:将列的数据类型指定为行版本

    DatabaseGeneratedAttribute:标记指定实体属性是由数据库生成的,并指定生成策略(None数据库不生成值,Identity当插入行时,数据库生成值,Computed当插入或更新行时,数据库生成值)

    TableAttribute:指定实体类对应的数据表名

    ColumnAttribute:指定实体属性在数据库中的列名

    ForeignKeyAttribute :指定导航属性的外键字段

    NotMappeAttribute:不映射对应字段

    映射方式二:Fluent API

    Fluent API的配置方式可以将实体类与映射配置进行解耦合

    有两种方式来实现Fluent API的映射配置

    • 第一种:重写Dbcontext的中OnModelCreating方法

    如下面的Book类,不再有Data Annotation特性

    public class Book
    {
        public int BookID { get; set; }
        public string BookName { get; set; }
        public int Pages { get; set; }
    }

    重写Dbcontext中的OnModelCreating方法实现Book类映射的配置:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Book>().HasKey(t => t.BookID);
    
        base.OnModelCreating(modelBuilder);
    }

    现实项目中,实体对象可能是非常多的,在OnModelCreating方法中逐一进行映射配置,可想而知会造成Dbcontext的代码庞大。

    • 第二种:新建BookMap类,并继承EntityTypeConfiguration<EntityType>

    1、在新建的BookMap类实现映射配置

    public class BookMap : EntityTypeConfiguration<Book>
    {
        public BookMap()
        {
            this.ToTable("Book", "dbo");
            this.HasKey(p => p.BookID);
            //this.HasKey(p => new { p.BookID, p.BookPreID });//关联主键  
            this.Property(p => p.BookID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);//自动生成
            this.Property(p => p.BookName).IsRequired().HasMaxLength(20).HasColumnName("BookName").IsUnicode(false);//非空,最大长度20,自定义列名,列类型为varchar而非nvarchar
            this.Ignore(p => p.BookDescription);//忽略改属性的映射
        }
    }

    2、依旧重写Dbcontext中的OnModelCreating方法,将BookMap 类的实例添加到modelBuilder的Configurations。

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new BookMap());
    }

    这样能大大减少OnModelCreating的代码量,依然存在一个问题,就是实体对象一多,还是要逐条将Map类的实例添加到modelBuilder的Configurations

    3、利用反射将程序集中所有的EntityTypeConfiguration添加到modelBuilder.Configurations中,可以说完全解耦了

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()
                            .Where(type => !String.IsNullOrEmpty(type.Namespace))
                            .Where(type => type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
        foreach (var type in typesToRegister)
        {
            dynamic configurationInstance = Activator.CreateInstance(type);
            modelBuilder.Configurations.Add(configurationInstance);
        }
    }

    注:此段代码源自网友文章,摘自nopCommerce项目的代码  连接

  • 相关阅读:
    学习&分享
    跳槽
    20121113:延期通知书
    2012.9.9 baocheng博客园正式与大家见面啦!
    数据库
    ASP.Net模板引擎
    javascript图片切换效果
    dockercompose环境下zookeeper单机搭建、集群搭建
    Linux服务器日常巡检脚本
    MMOS FFB伺服直驱方向盘主控板DIY
  • 原文地址:https://www.cnblogs.com/qiuguochao/p/10261244.html
Copyright © 2011-2022 走看看