zoukankan      html  css  js  c++  java
  • Entity Framework——建模建库

    1数据库初始化策略选择

    三种初始化策略:

    1)CreateDatabaseIfNotExists:默认的策略如果数据库不存在,那么就创建数据库。但是如果数据库存在,而且实体发生了变化,就会出现异常。

    2)DropCreateDatabaseIfModelChanges:模型改变时,原来的数据库会被删除,自动重新创建一个新的数据库

    3)DropCreateDatabaseAlways:每次运行都会删除原来的数据库,然后重新生成数据库。

    4)Null:在Codefirst模式下,当实体结构改变时,运行程序不会自动生成表,改变实体结构与改变表结构互不影响,

    前三种策略无法应对的问题是:分别改变实体模型和数据库表结构。即,当使用CreateDatabaseIfNotExists策略时,修改实体模型会抛异常(The model backing the <Database> context has changed since the database was created

    );若使用DropCreateDatabaseIfModelChanges模式,那么每次运行都会重新生成数据库,这导致历史数据丢失,然而提前备份数据这种策略比较麻烦,尤其是系统上线以后。

    解决办法:

    采用第四种初始化策略,初次使用codefirst方式创建好数据库以后,不使用任何数据库初始化策略,即给Database.SetInitializernull。

    [DbConfigurationType(typeof(MySqlEFConfiguration))]
    public class HY_WebApiContext : DbContext
    {
      public HY_WebApiContext(): base("name=HY_WebApiContext")
      {
        Database.SetInitializer<HY_WebApiContext>(null);
      }
      ......
    }

    2实体关系与依赖默认规则创建的表关系

    Codefirst模式下,实体与表之间的映射,随实体关系的不同而不同。

    1)实体之间为一对一关系

    实体

         public class EntityOne
            {
                public int Id { get; set; }
                public string FieldEntityOne { get; set; }
                public EntityTwo EntityTwo { get; set; }
            }
    
            public class EntityTwo
            {
                public int Id { get; set; }
                public string FieldEntityTwo { get; set; }
            }

    表结构

    entityones,其中EntityTwo_Id为外键。

    EntityTwo

    2)实体间的一对多关系

    实体

         public class EntityOne
            {
                public int Id { get; set; }
                public string FieldEntityOne { get; set; }
                public List<EntityTwo> EntityTwos { get; set; }
            }
    
            public class EntityTwo
            {
                public int Id { get; set; }
                public string FieldEntityTwo { get; set; }
            }

    表结构

    entityones

    entitytwoes,其中EntityOne_Id是外键

    3)实体间的多对多关系

    实体

         public class EntityOne
            {
                public int Id { get; set; }
                public string FieldEntityOne { get; set; }
                public List<EntityTwo> EntityTwos { get; set; }
    
            }
    
            public class EntityTwo
            {
                public int Id { get; set; }
                public string FieldEntityTwo { get; set; }
            public List<EntityOne> EntityOnes { get; set; }
            }

    表结构

    Codefirst模式下,两个实体间的多对多关系,映射为三张表,其中一张表表示实体间的联系。

    entityones

    entitytwoes

    entitytwoentityones,其中EntityTwo_IdEntityOne_Id是外键,这两个外键构成了改表的复合主键。

    4)实体包含类型相同的两个或多个名称不同的导航属性

    实体

    public class EntityOne
    {
         public int Id { get; set; }
         public string FieldEntityOne { get; set; }
         public EntityTwo EntityTwos { get; set; }
         public EntityTwo EntityTwosOther { get; set; }
    }
    
     public class EntityTwo
     {
         public int Id { get; set; }
         public string FieldEntityTwo { get; set; }
     }

    Entityones,其中EntityTwos_IdEntityTwosOther_Id是外键。

    entitytwoes

    3为关系创建实体:

    一个用户可以订阅多种出版物,一种出版物可被多个用户订阅,实体建模如下:

    public class Publication
    {
      public int Id { get; set; }
      public virtual ICollection<User> Users { get; set; }
      ......
    }
    
    public class User
    {
      public int Id { get; set; }
      public virtual ICollection<Publication> Publications { get; set; }
      ......
    }

    EF框架对上述多对多关系的默认处理方式为生成三张表:publications,user,publicationusers

    其中publicationusers为关系表,表的属性只包括两个表的主键。

    问题1publications表的数据会大量重复:假设用户A订阅了电子学报,publications表里会有一条关于电子学报的记录,当用户B也订阅电子学报的时候,又会将这条数据插入publications表,如此等等。

    解决方案

    每次向publications表插入记录时,先在表中查找待插入的刊物是否存在,如果存在就不插入,只更新publicationusers表。

    问题2:虽然使用上面的方法可以解决这个问题,但用户何时订阅了一种刊物,这类信息没有被记录下来。

    解决方案:

    添加一个实体,表达publications,user这两个实体之间的关系,实体如下:

    public class Publication
    {
      public int Id { get; set; }
      ......
    }
    public class User
    {
      public int Id { get; set; }
      ......
    }
    
    public class PublicationUser
    {
            public int Id { get; set; }
            /// <summary>
            /// 出版物
            /// </summary>
            public Publication Publication { get; set; }
            /// <summary>
            /// 所属用户
            /// </summary>
            public User User { get; set; }
            /// <summary>
            /// 记录插入时间
            /// </summary>
            public DateTime InsertTime { get; set; }
            /// <summary>
            /// 记录修改时间
            /// </summary>
            public DateTime UpdateTime { get; set; }
    }

    经上述处理后,EF仍然生成三张表publications,user,publicationusers,与之前不同的是publicationusers表中多了Id ,InsertTime ,UpdateTime 这三个字段,同时去掉了publications,user其中的导航属性,这样的设计满足需求,且无冗余。那么经过这样的修改后,每一个PublicationUser实例对应了表中的一条记录。

  • 相关阅读:
    Mysql Window 解压版卸载
    maven jdk 版本配置
    单点登录原理与简单实现
    JAVA HASHMAP的死循环
    Intellij IDEA 4种配置热部署的方法
    springmvc 返回 404 解决
    设计模式 -- 模版模式
    安装Oracle Database 11g 找不到文件“WFMLRSVCApp.ear” .
    红黑树 -- 增删查改
    TIJ -- CountDownLatch
  • 原文地址:https://www.cnblogs.com/hdwgxz/p/7954799.html
Copyright © 2011-2022 走看看