EF 6及以前的版本是預設支持延遲載入(Lazy Loading)的,早期的EF Core中並不支持,必須使用Include方法來支持導航屬性的數據載入。 當然在 EF Core 2.1 及之後版本中已經引入了延遲載入功能,詳細實現原理可以查看官網( "傳送門" )。 下麵記錄一下,分別使用Incl ...
EF 6及以前的版本是預設支持延遲載入(Lazy Loading
)的,早期的EF Core中並不支持,必須使用Include
方法來支持導航屬性的數據載入。
當然在EF Core 2.1及之後版本中已經引入了延遲載入功能,詳細實現原理可以查看官網(傳送門)。
下麵記錄一下,分別使用Include
和Lazy Loading
來支持導航屬性的數據載入。
Entity資料庫實體
簡單的一個多對多關係,分別對應資料庫中的3張表。學生和學校之間通過StuSchReg關聯,相互之間可以通過導航屬性獲取數據。
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public virtual IList<StuSchReg> Regs { get; set; }
}
public class School
{
public int Id { get; set; }
public string Name { get; set; }
public virtual IList<StuSchReg> Regs { get; set; }
}
public class StuSchReg
{
public int Id { get; set; }
public int StdId { get; set; }
[ForeignKey("StdId")]
public virtual Student Student { get; set; }
public int SchId { get; set; }
[ForeignKey("SchId")]
public virtual School School { get; set; }
}
通過導航屬性獲取數據
數據查詢需求:通過學校Id獲取學校中所有學生的信息
[HttpGet]
[HttpPost]
public async Task<JsonResult> Test(int id)
{
return await Task.Run(() =>
{
var school = dbContext.School.Find(id);
var list = school.Regs.Select(d => new { d.Student.Id, d.Student.Name });
return Success(list);
});
}
這種情況下school.Regs
會報錯(未將對象引用到實例),斷點查看會發現值為null。
解決方法:
1.通過Include
直接載入導航屬性
將獲取school的語句修改一下,可以正常獲取到數據。
var school = dbContext.School
.Include(d => d.Regs)
.ThenInclude(d => d.Student)
.FirstOrDefault(d => d.Id == id);
2.開啟EF Core的延遲載入功能
使用延遲載入的最簡單方式是安裝 Microsoft.EntityFrameworkCore.Proxies 包,並通過調用 UseLazyLoadingProxies 來啟用。
例如:在DbContext的OnConfiguring
方法中啟用
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseLazyLoadingProxies()
.UseSqlServer(myConnectionString);
}
或在使用AddDbContext
時啟用
services.AddDbContext<BloggingContext>(
b => b.UseLazyLoadingProxies()
.UseSqlServer(myConnectionString));
EF Core會為可重寫的任何導航屬性(必須是 virtual 且在可被繼承的類上)啟用延遲載入。
這時候還原為最開始的調用方式,也可以正常獲取到導航屬性的數據了。
var school = dbContext.School.Find(id);