zoukankan      html  css  js  c++  java
  • EF实体类配置总结

    实体类配置总结

    Entity Framework 6 Code First 实践系列(1):实体类配置总结

    2014-03-25 12:58 by TJerry, 719 阅读, 6 评论, 收藏编辑

    EF实体类的配置可以使用数据注释或Fluent API两种方式配置,Fluent API配置的关键在于搞清实体类的依赖关系,按此方法配置,快速高效合理。为了方便理解,我们使用简化的实体A和B以及A、B的配置类AMap和BMap,来演示如何正确配置实体类关系的过程。

     实体类配置

    一、确定依赖关系:

    假设实体B依赖于实体A(B->A),那么实体B中存在对实体A的引用。

    二、实体类配置应该写在哪里?

    假设B依赖于A(B->A),很显然,我们希望的是B表中生成外键(A表的主键值)。以下两种方式都可以实现相同的表结构,但毫无疑问我们应该在B的配置文件BMap中进行关系配置。

    (1)B依赖于A,A可以对B的存在一无所知。

    (2)A可以单独存在,配置写在哪里都不会对A表产生影响。

    (3)B对A的依赖是通过在B表中生成外键(A表的主键)。

    推荐的写法:

    public class BMap : EntityTypeConfiguration<B> { public BMap() { this.HasRequired(o => o.A).WithMany(o=>o.ListB); } }

    摒弃的写法

    public class AMap : EntityTypeConfiguration<A> { public AMap() { this.HasMany(o => o.ListB).HasRequired(o => o.A); } }

    依赖的方向决定了使用的配置,这在实体类数量和关系复杂时尤其重要,假设有10个实体类依赖A,混合书写配置显然不可取,而在被依赖实体中配置的结果会导致经常修改A的配置文件,你甚至不肯定修改了类A的配置文件是会引起A表的变化。

    三、配置依赖关系

    配置文件的基类EntityTypeConfiguration包含了一系列Has方法用来配置实体类,其中HasOptional和HasRequired根据实体的引用属性配置实体关系。假设B依赖于A(B->A),HasOptional允许B单独存在,这将在B表中生成可空的外键。HasRequired不允许B单独存在,这将在B表中生成非空的外键。

     HasRequired
     HasOptional

    四、配置关联类型

    HasOptional和HasRequired分别返回OptionalNavigationPropertyConfiguration和RequiredNavigationPropertyConfiguration对象,我们使用其中的WithMany和WithOptional来配置关联的类型。

    如果A:B = 1:N,我们使用WithMany。

     1:N(外键可空)
     1:N(外键不可空)

    如果A:B= 1:1,我们使用WithOptional。1:1的关联要求外键的非空和唯一,数据库是通过表B的外键作为主键来实现

     1:1

    四、可选导航属性

    导航属性由关联类型决定,但其存在与否不会影响实体的依赖关系和关联类型。

    对于B->A,如果A:B = 1:N,我们可以在A中添加ICollection<B>类型的导航属性,同时修改关系配置,将该属性传递给WithMany方法。

     导航属性

    如果A:B = 1:1,我们可以在A中添加B类型的导航属性,同时修改关系配置,将该属性传递给WithOptional方法。

     导航属性

    五、显式外键属性

    对于B->A,如果A:B = 1:1,外键就是主键。

    如果A:B = 1:N,我们可以自定义导航属性对应的外键属性,首先在B中添加显式的用于外键的属性。

     显式外键

    WithMany返回DependentNavigationPropertyConfiguration对象,我们使用该对象的HasForeignKey方法,如果实体联系配置为HasOptional,则需要使用可空类型匹配。

     外键配置

    六、级联删除配置

    HasForeignKey返回CascadableNavigationPropertyConfiguration对象,EF默认开启级联删除,当实体关系复杂导致无法开启级联删除时,我们使用该对象的WillCascadeOnDelete方法配置取消级联删除。

    七、关于双向依赖

    EF中实体的关联通过表的外键实现,1:N还是1:1都是通过外键实现。我们可以根据1:N配置的方式配置出双向依赖的表,但通常所谓的多对多都不是双向依赖。例如用户和角色、学生和课程、文章和标签等,甚至根本没有依赖,因为二者都可以独立存在,有的只是映射关系对二者的依赖,而这是1:N的问题。

    我们使用EntityTypeConfiguration配置实体依赖,该类的ToTable、HasKey等实例方法都用于配置当前实体类映射的Table。HasRequired和HasOptional方法也会在对应的Table中生存外键,而HasMany方法则是其中的异类,偏偏配置的非当前实体类。

    HasMany、WithMany除了在配置双向引用时替我们自动生成关系表,带来更多的是配置混乱。而所谓的自动生成关系表更是打破了我们实体类和Table的一一对应。在Microsoft.AspNet.Identity.EntityFramework 1.0中,我们可以看到IdentityUser和IdentityRole并没有通过双向引用自动生成关系表,而是定义了IdentityUserRole实体类用来映射:通过IdentityDbContext<TUser>的OnModelCreating配置我们可以看到虽然使用了HasMany配置TUser的Roles属性,但是完全可以在IdentityUserRole中配置。即使在2.0版本中依旧如此。

    、常见的配置举例:

    1.用户和角色: 

    (1)确定依赖关系:User和Role都可以单独存在,但UserRole不可以单独存在,因此存在的依赖是UserRole->User,UserRole->Role。

    (2)配置依赖关系:UserRole不能单独存在,因此使用HasRequired。

    (3)确定关联类型:User:UserRole==1:*;Role:UserRole=1:*,因此使用WithMany。

    (4)显式的外键属性:在UserRole中添加UserId和RoleId作为显式的外键属性。

    (5)可选的导航属性:在User和Role中添加ICollection<UserRole>类型的导航属性。

    UserRole不应该存在重复的用户角色映射,因此使用外键作为联合主键。

     UserRole

    2.节点树:

    (1)确定依赖关系:Category自依赖,Category->Category

    (2)配置依赖关系:Category可以单独存在,因此使用HasOptional。

    (3)确定关联类型:Category:Category==1:*,因此使用WithMany。

    (4)显式的外键属性:在UserRole中添加ParentId,由于Category可以单独存在,ParentId为可空类型。

    (5)可选的导航属性:在Category中添加ICollection<Category>类型的导航属性。

     Category->Category
    作者:Tjerry 
  • 相关阅读:
    剑指Offer-11.二进制中1的个数(C++/Java)
    剑指Offer-10.矩形覆盖(C++/Java)
    剑指Offer-9.变态跳台阶(C++/Java)
    UVA 1608 Non-boring sequence 不无聊的序列(分治,中途相遇)
    UVA1607 Gates 与非门电路 (二分)
    UVA 1451 Average平均值 (数形结合,斜率优化)
    UVA 1471 Defense Lines 防线 (LIS变形)
    UVA 1606 Amphiphilic Carbon Molecules 两亲性分子 (极角排序或叉积,扫描法)
    UVA 11134 FabledRooks 传说中的车 (问题分解)
    UVA 1152 4 Values Whose Sum is Zero 和为0的4个值 (中途相遇)
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3624614.html
Copyright © 2011-2022 走看看