zoukankan      html  css  js  c++  java
  • EF--主外键关系导航属性

    • 数据准备
      公司表Company和员工表Employee两张表创建主外键强关系,员工表Employee的Company_ID是公司表Company的外键,如下图所

    • 解读主外键生成的实体特殊性

    Company实体--主外键关系的话,EF生成的实体,主表Company实体有个子表Employee的集合,注意这个集合是virtual虚拟的

    Employee实体--子表里面还有个主表Company的实例,引用属性,注意主表实体Company也是virtual虚拟的

    • 导航属性是延迟查询

    我们看到我们只查询公司ID是“0000000001”的公司,并没有主动去查询这个公司下面的员工并没有生成查询员工的sql,但是当我们遍历公司员工company.Employee的时候EF主动帮我们查询了得到这个公司下面的员工,所以证明导航属性是延迟查询,只有在真正使用的时候才去查询“0000000001”这个公司下面的员工,条件是virtaul属性(Employees是虚拟的)+ 默认配置(dbContext.Configuration.LazyLoadingEnabled = true;懒加载配置是true)

    public class EFNavTest
    {
        public static void Show()
        {
            {
                using (SchoolDBEntities dbContext = new SchoolDBEntities())
                {
                    var companyList = dbContext.Set<Company>().Where(c => c.Company_ID == "0000000001");
                    foreach (var company in companyList)//只查company
                    {
                        Console.WriteLine(company.Company_Name);
                        foreach (var employee in company.Employees)
                        {
                            Console.WriteLine(employee.Employee_Name);
                        }
                    }
                    Console.Read();
                }
            }
        }
    }

     

    • 关闭延迟加载,子表的数据就没有了

    dbContext.Configuration.LazyLoadingEnabled = false;

    {
        using (SchoolDBEntities dbContext = new SchoolDBEntities())
        {
            dbContext.Configuration.LazyLoadingEnabled = false;//关闭延迟查询
            var companyList = dbContext.Set<Company>().Where(c => c.Company_Id == 02);
            foreach (var company in companyList)//只查company
            {
                Console.WriteLine(company.Company_Name);
                foreach (var employee in company.Employees)
                {
                    Console.WriteLine(employee.Employee_Name);
                }
            }
        }
    }

    • Include预先加载

    预先加载,Include查询主表Company时就把子表数据Employee一次性查出来,和上面导航属性的懒加载不同,不同之处在于上面是当使用company.Employee的时候EF主动帮我们查询了得到这个公司下面的员工,而Include查询主表Company时就把子表数据Employee一次性查出来了不管你有没有用,我们从EF生成的sql语句就能看出来是个左外连接,它是把0000000001这个公司和它下面的员工一下都查询出来了

    {
        //3、预先加载,Include查询主表时就把子表数据一次性查出来
        using (SchoolDBEntities dbContext = new SchoolDBEntities())
        {
            dbContext.Configuration.LazyLoadingEnabled = false;//是否关闭无所谓
            var companyList = dbContext.Set<Company>().Include("Employees").Where(c => c.Company_Id == "0000000001");
            foreach (var company in companyList)//只查company
            {
                Console.WriteLine(company.Company_Name);
                foreach (var employee in company.Employees)
    { Console.WriteLine(employee.Employee_Name);
    } } } }

    • 关闭延迟查询后,不想使用Include一次性查询子表的数据,只是需要子表的数据,才要查询,Collection可以显式加载

    当执行了dbContext.Entry<Company>(company).Collection(c => c.Employees).Load();这句代码,就会生成查询该公司下的员工的sql语句,就会查询该公司的员工

    {
        //4、关闭延迟查询后,如果需要子表数据,可以显示加载
        using (SchoolDBEntities dbContext = new SchoolDBEntities())
        {
            dbContext.Configuration.LazyLoadingEnabled = false;
            var companyList = dbContext.Set<Company>().Where(c => c.Company_Id == "0000000001");
            foreach (var company in companyList)//只查company
            {
                 Console.WriteLine(company.Company_Name);
                dbContext.Entry<Company>(company).Collection(c => c.Employees).Load();
                foreach (var employee in company.Employees)
                {
                    Console.WriteLine(employee.Employee_Name);
                }
            }
        }
    }

    • 闭延迟查询后,如果需要主表数据,Reference可以显式加载

    当执行了dbContext.Entry(employee).Reference(s => s.Company).Load();这句代码,就会生成查询该员工的公司的sql语句,就会查询该员工的公司

    //5、关闭延迟查询后、如果需要主表数据,可以显示加载
    using (SchoolDBEntities dbContext = new SchoolDBEntities())
    {
        dbContext.Configuration.LazyLoadingEnabled = false;
        var employeeList = dbContext.Set<Employee>().Where(s => s.Employee_ID == "0000000001");
        foreach (var employee in employeeList)
        {
            Console.WriteLine(employee.Employee_Name);
            dbContext.Entry<Employee>(employee).Reference(s => s.Company).Load();
            string companyName = employee.Company.Company_Name;
            Console.WriteLine(companyName);
        }
    }

    • 结论

    根据上面的阐述,可以表与表之间不必建立强关系,可以表与表非主外键关系建立导航属性,一般来说,主表有个子表的集合导航属性(像上述的public virtual ICollection<Employee> Employees { get; set; },注意必须是virtual虚拟的),子表里面还有个主表的实例(像上述的 public virtual Company Company { get; set; },注意必须是virtual虚拟的),引用属性,就可以了

  • 相关阅读:
    第二次冲刺每日站立会议10(完结)
    第二次冲刺每日站立会议09
    第二次冲刺每日站立会议08
    找bug
    测试计划
    博客园的意见与建议
    第二次每日站立会议07
    个人总结
    学习进度条(第十六周)
    梦断代码阅读笔记03
  • 原文地址:https://www.cnblogs.com/menglin2010/p/12255343.html
Copyright © 2011-2022 走看看