EF--主外鍵關係導航屬性

  • 數據準備
    公司表Company和員工表Employee兩張表創建主外鍵強關係,員工表Employee的Company_ID是公司表Company的外鍵,如下圖所

  • 解讀主外鍵生成的實體特殊性

Company實體--主外鍵關係的話,EF生成的實體,主表Company實體有個子表Employee的集合,注意這個集合是virtual虛擬的

Employee實體--子表裏面還有個主表Company的實例,引用屬性,注意主表實體Company也是virtual虛擬的

  • 導航屬性是延遲查詢

我們看到我們只查詢公司ID是“0000000001”的公司,並沒有主動去查詢這個公司下面的員工並沒有生成查詢員工的sql,但是當我們遍歷公司員工company.Employee的時候EF主動幫我們查詢了得到這個公司下面的員工,所以證明導航屬性是延遲查詢,只有在真正使用的時候纔去查詢“0000000001”這個公司下面的員工,條件是virtaul屬性+默認配置

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虛擬的),引用屬性,就可以了

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章