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项目的代码  连接

原文地址:https://www.cnblogs.com/qiuguochao/p/10261244.html

时间: 2024-10-14 23:42:54

Entity Framework 查漏补缺 (三)的相关文章

Entity Framework 查漏补缺 (一)

明确EF建立的数据库和对象之间的关系 EF也是一种ORM技术框架, 将对象模型和关系型数据库的数据结构对应起来,开发人员不在利用sql去操作数据相关结构和数据.以下是EF建立的数据库和对象之间关系 关系数据库 对象 数据库 DbContext类 表 DbContext中的DbSet<实体类名> 表间的关联 实体类之间的关联 字段 实体类的公有属性 单条数据 单个实体类的对象 约束(主键.外键默认值) 实体类中的特性 了解EDM( 实体数据模型) EF使用概念模型. 映射和存储模型.三个模型来描

Entity Framework 查漏补缺 (二)

数据加载 如下这样的一个lamda查询语句,不会立马去查询数据库,只有当需要用时去调用(如取某行,取某个字段.聚合),才会去操作数据库,EF中本身的查询方法返回的都是IQueryable接口. 链接:IEnumerable和IQueryable接口说明 其中聚合函数会影响数据加载,诸如:toList(),sum(),Count(),First()能使数据立即查询加载. IQueryable中的Load方法 一般情况,我们都是使用ToList或First来完成预先加载数据操作.但在EF中还可以使用

java知识查漏补缺

一.重写(override)和重载(overload)的区别 二者除了名字相似,其实没什么联系 范围不同:重写发生在同一个类的不同方法之间.重载发生在父类和子类自荐. 前提: 重写要求:方法名相同,参数列表不同,对于返回值类型不要求相同. 重载要求:方法名形同,参数列表也相同.重载是实现多态的关键,注意如果父类中的方法是private类型,那么子类中对应方法不算重载,而相当于是定义了一个新方法. 二.final的用法 修饰类:该类不能被继承 修饰方法:该方法不能被重写 修饰属性:该属性初始化后不

查漏补缺1

前言 Java的部分有基础.设计模式.IO.NIO.多线程,之后有时间还会把集合这 部分补上去,这么多内容里面,难免有一些知识点遗漏,本文主要是讲解这些遗漏的知识点.这些知识点,不是特别大的难点,所以没有必要专门写一篇文章讲解: 但是这些知识点,也不是一两句话就说得清楚的,所以放在这里.查漏补缺系列文章,每篇5个知识点,只要有值得研究的问题就会写上来. Thread.sleep(XXX)方法消耗CPU吗? 这个知识点是我之前认识一直有错误的一个知识点,在我以前的认识里面,我一直认为 Thread

20165239其米仁增第一周查漏补缺

第一周查漏补缺 上周我没有在课堂上完成考试内容,原因有以下几点: 第一,课余时间没有好好去敲课本上的java代码,我以后会在课余时间好好完成作业. 第二,因为今年寒假我回老家过年,那里没有网络,没有收到消息,所以在假期自学的时间比较短,在加上我自己母语是藏语,对汉文的理解能力有限,不像其他同学那样,自学起来就比较困难 第三:自己遇到问题时没有积极主动去找同学帮忙,而是自己一个人在那儿瞎弄,导致效率低下: 这周我吸取了上次考试的教训把第一章好好学了一遍,从java的网络,语言,需求等地位道java

第四周查漏补缺

第四周查漏补缺 第三周课下测试总结 课堂测试 考试时,题目要求的"N由命令行传入"我还没学会.于是编辑了以下代码,可以运行.通过键入N值来实现算法: 在课下学习中,还发现这段代码我用了两个类..在这个算法中没有对象,可以不需要用两个类,而且不同类应该单独存一个.java文件. 但我依然没有理解什么时候该分不同类对不同对象实现不同方法... 经过学习和修改后我修改了代码: 然后测试发现:输入5322,返回值sum太大溢出了.于是我把sum的类型改为了long,成功输出了值. 在和小组同学

近来的java小总结(2.1):类的知识的查漏补缺

首先,我是一名新手,所以,要带着批判的眼光来看下面的文章   这篇文章说了些什么? 这文章是我近来8.6号来在编程思想上打的代码,从0~200页的源码接近到在这里,下文正是总结这0~200页的的知识,涉及到接口,内部类.初始化,数值计算的一些细节.此文章不会一下子写完,可能隔一天可能再补下来.因为代码确实有点多.. 注意 1 我的注释不一定正确(不过各小标题和代码一定是正确的,因为是书本上的原话,但是注释不一定正确),如果你确信我的内容的话,你可能会损失很大,因为我只是个菜鸟,我只是来补救一些知

查漏补缺——java多态

---恢复内容开始--- 刚学完java,开始了查漏补缺阶段阶段,为了巩固自己的知识和为别人提供一些微末的帮助决定开通博客,求各位大牛们指出我的不足,不要吝惜言语,也希望我的总结可以对别人有帮助,对自己对他人负责. 开始正文:术语多态:可以定义为“有多种形态”,多态引用是一个一个在不同时刻可以指向不同类型对象的引用变量.通过多态引用可以调用不同的具体的方法. 类方法的多态性的实现有两种方式: 1:方法重载:可以声明多个同名但是参数不同(个数.类型和顺序)的方法.注意呵呵重载方法只能声明在一个类里

近来的java小总结(2.2):类的知识的查漏补缺

1 首先,我是一名新手,所以,要带着批判的眼光来看下面的文章   这篇文章说了些什么? 这文章是我近来8.6号来在编程思想上打的代码,从0~200页的源码接近到在这里,下文正是总结这0~200页的的知识,涉及到接口,内部类.初始化,数值计算的一些细节.此文章不会一下子写完,可能隔一天可能再补下来.因为代码确实有点多.. 注意 1 我的注释不一定正确(不过各小标题和代码一定是正确的,因为是书本上的原话,但是注释不一定正确),如果你确信我的内容的话,你可能会损失很大,因为我只是个菜鸟,我只是来补救一