• EF实体框架处理实体之间关联关系与EF延迟机制(下)


           在数据库中,表与表之间可能存在多种联系,比如,一对多,多对多的关系。当我们使用逻辑外键在数据库建立两张表之间的关系的时候,我们使用EF实体框架  

    必然也会将这种关系映射到我们的实体关系中来。所以,在我们做项目的时候,很多情况下我们都使用逻辑外键建立两张表之间的关系,从而避免删除等操作带来的种  

    种问题。  

          那么,我们的EF实体框架是怎么解决这种关联关系呢?假如给我们两张表,一张是用户表,另外一张是订单表。用户表与订单表是一对多的关系,我们来仿照EF  

    代码简单的写一个自己的框架(CodeOnly)  

          第一步:建两个类UserInfo和Order类  

          下面这时UserInfo类:  

     1 namespace codeOnly
     2 {
     3    public  class UserInfo
     4     {
     5         [Key]
     6         public int Id { get; set; }
     7         public string UName { get; set; }
     8         //这里显示了一对多的关系,一个用户可以有多个Order表
     9         public ICollection<Order> Order { get; set; }
    10     }
    11 }

       下面这是Order类  

    namespace codeOnly
    {
       public  class Order
        {
           [Key]
            public int Id { get; set; }
            public string Content { get; set; }
            //一个Order对应一个User
            public UserInfo User { get; set; }
        }
    }

      这样便解决了一对多的关系,多对多的实现也是如此,那么我们再来看看它的上下文的实现过程吧  

     1 namespace codeOnly
     2 {
     3    public  class DbContentDemo:DbContext
     4     {
     5        //实现了.Net与数据库的连接
     6        public DbContentDemo()
     7            : base("name=Demo")
     8        {
     9            
    10        }
    11        public DbSet<UserInfo> UserInfo { get; set; }
    12        public DbSet<Order> Order { get; set; }
    13     }
    14 }

             看到这里,我们是不是就想起了HttpContext这个类呢,简直是具有异曲同工之处呢。前边也已经介绍了上下文的作用,这里就不再多说了,主要介绍一下其  

    中“name=Demo”的作用。在App.config下:Demo就是与数据库进行连接的字符串。所以它在内部实现了与数据库进行连接的操作。下面这段代码就可以实现在数  

    据库中创建与我们的实体一一对应的表格了。  

     1 namespace codeOnly
     2 {
     3     class Program
     4     {
     5        public  static void Main(string[] args)
     6         {
     7             DbContentDemo dbcontext = new DbContentDemo();
     8             //初始化数据库
     9             dbcontext.Database.CreateIfNotExists();//如果数据库不存在则自动创建
    10             UserInfo user = new UserInfo();
    11             user.Id = 5;
    12             user.UName = "大家好";
    13             dbcontext.SaveChanges();
    14             Console.ReadKey();
    15         }
    16     }

             上面这些代码颇为简单,相信大家都能看明白EF实体框架内部的处理过程是怎样的了(这是ModelFirst的情况),那么在DbFirst的情况下处理一对多多对多的关系  

    我们也简单的用一段小代码来诠释吧。  

     1 namespace ModelFirstaaaa
     2 {
     3     class Program
     4     {
     5         static void Main(string[] args)
     6         {
     7             //一对多的关系
     8             Model1Container dbContext=new Model1Container();
     9             UserInfo user=new UserInfo();
    10             user.ID = 5;
    11             user.IsDel = "false";
    12             user.Phone = "13363605745";
    13             user.SubTime=DateTime.Now;
    14             user.UName = "大家好";
    15             dbContext.UserInfo集.AddObject(user);
    16 
    17             Order order=new Order();
    18             order.ID = 5;
    19             order.Content = "你哈";
    20             order.UserInfo = user;
    21 
    22             dbContext.SaveChanges();
    23             Console.WriteLine("执行成功");
    24             Console.ReadKey();
    25 
    26             //多对多的关系
    27 
    28             #region  多对多的关系
    29             Model1Container dbContext = new Model1Container();
    30             UserInfo user = new UserInfo();
    31             user.ID = 6;
    32             user.IsDel = "false";
    33             user.Phone = "13363605745";
    34             user.SubTime = DateTime.Now;
    35             user.UName = "me";
    36             dbContext.UserInfo集.AddObject(user);
    37 
    38             Order order = new Order();
    39             order.Content = "你好";
    40             order.ID = 7;
    41             dbContext.Order.AddObject(order);
    42 
    43             order.UserInfo.Add(user);
    44             dbContext.SaveChanges();
    45             Console.WriteLine("ok");
    46             #endregion
    47    }
    48   }
    49 }

                  另外,EF还有一个很优美的特定,那就是延迟加载的特性。EF       中第一个延迟加载机制:当我们用到的时候才会去加载数据。每次使用的时候都会全新为我们加       

    载数据。使用多少次便查询多少次      。当我们使用Linq表达式写一个查询语句的时候,返回的结果基本上都是一个       IQuerable       类型集合,数据库的sql执行的顺序一般为from,       

          where,select......而我们EF实体框架将程序编译成sql脚本的时候 先把执行的顺序根据算法生成树的形式(编译原理),根节点是       from,       先中间,后左边,然后最右边。       

    有可能继续      而我们       C#       提供的       Expression       类型就为我们提供了树的结构。我们写的       Linq       表达式最终只不过是将       Linq       生成了表达式放到了       Expression       表达式类型中去了。放到了       

    IQueryable       内部中去了。我们用到的       IQueryable       接口的集合的时候,       IQuerable       集合内部的       Provider       属性会解析       Expression,       然后生成相应的sql语句去做相应查询并加载数据。       

         

    1 var data = dbContext.ClassInfo.Where(c => c.ClassName.Contains("计算机"));
    2   foreach (var classinfor in data)
    3     {
    4         Console.WriteLine(classinfor.ClassId+classinfor.ClassName);
    5     }

       

    2.第二种延迟加载机制:  

         导航属性的延迟加载机制:如果实体是查询出来的,那么通过导航属性去访问其它有关联的实体的时候       EF       会自动帮我们去查询关联表的数据。不管有没有       ToList,       

    导航属性      有个需求:缓存。       IQueryable       是一个非常特殊的接口,数据并不存放在本地,只有用到的时候通过       Provinder       去解析加载数据       (       它本身是不存储数据的       )       。而我们       

    List       ,       Array(实现了IEnumrable接口,可以对数组进行遍历)       都是一个本地集合      。Var  users=(from u in dbHmEntities select u).ToList();当查询成功的       时候就相       

    当于将数据库中的内容立刻加载到内存中,这时候使用       foreach       遍历集合的时候就不会去执行       sql       脚本了。       FirstOrDefault       也是立即去查询。                 

    1     //IQueryable:是非常特殊的接口,数据并不存放在本地,只有用到的时候去解析Exp加载数据。
    2             var data2 = dbContext.ClassInfo.Where(c => c.ClassName.Contains("计算机")).ToList();
    3             foreach (var classinfo in data2)
    4             {
    5               Console.WriteLine(classinfo.ClassName+classinfo.ClassId);
    6             }
  • 相关阅读:
    求约数的个数-牛客
    成绩排序 -- 牛客
    SpringBoot学习笔记4-整合Jdbc Template-Mybatis-多数据源-事务管理-JPA
    SpringBoot学习笔记3-自定义拦截器-全局异常处理-Freemarker-Thymeleaf-定时任务调度
    SpringBoot学习笔记2-日志管理-开发模式-web开发-FastJson
    SpringBoot学习笔记1-简介-全局配置文件-starter-profiles-自动配置原理
    将Ueditor文件上传至OSS
    nouveau :failed to create kernel chanel,-22
    教你怎么炼鸡肉
    教你怎么写猜年龄游戏
  • 原文地址:https://www.cnblogs.com/liangxiaofeng/p/5809027.html
Copyright © 2020-2023  润新知