簡體   English   中英

您何時需要在實體框架中包括相關實體?

[英]When do you need to .Include related entities in Entity Framework?

在我必須實際使用.Include()相關實體時,以及在我不需要時,這對我來說似乎是任意的。 在某些情況下,EF不提供相關實體的信息給我,而在其他情況下,EF無法對相關實體做任何事情,因為我沒有包括它們:

不帶.include()的作品;

這是我不使用.Include()加載數據的示例;

public class InvoiceService
{
    private ApplicationDbContext db { get; set; }
    public InvoiceService(ApplicationDbContext context)
    {
        db = context;
    }

    public Invoice Get(int id)
    {
        return db.Invoices.SingleOrDefault(x => x.Id == id);
    }
}

public partial class ShowInvoice : System.Web.UI.Page
{
    private InvoiceService invoiceService;

    private readonly ApplicationDbContext context = new ApplicationDbContext();
    protected void Page_Load(object sender, EventArgs e)
    {
        invoiceService = new InvoiceService(context);
        if (!IsPostBack)
        {
            int.TryParse(Request.QueryString["invoiceId"].ToString(), out int invoiceId);
            LoadInvoice(invoiceId);
        }
    }

    private void LoadInvoice(int invoiceId)
    {
        var invoice = invoiceService.Get(invoiceId);
        // Other code irrelevant to the question goes here.
    }
}

以下是結果,其中包括與我請求的發票相關的公司數據: 在此處輸入圖片說明

如您所見,該公司的信息肯定來自但未明確包含。

如果沒有.include(),則無法使用;

相反,在同一個項目中,我已經完成了一些與發票的映射,並且在獲取相關實體的屬性值時會得到NullReferenceExceptions,因為我沒有.Include()

此方法獲取指定公司的所有批准的時間表條目。 此視圖模型僅在處理發票的時間表條目的關聯時使用(因此,您根據選定的時間表條目進行發票)。

public List<InvoiceTimesheetViewModel> GetInvoiceTimesheetsByCompanyId(int companyId)
{
    var factory = new TimesheetViewModelsFactory();

    var timesheets = db.Timesheets.Where(x => x.Approved && x.Company.Id == companyId && !x.Deleted).ToList();
    return factory.GetInvoiceTimesheetsViewModel(timesheets);
}

NullReferenceExceptions發生在工廠中,該工廠將時間表實體映射到視圖模型:

public List<InvoiceTimesheetViewModel> GetInvoiceTimesheetsViewModel(List<Timesheet> timesheets)
{
    var model = new List<InvoiceTimesheetViewModel>();
    foreach (var timesheet in timesheets)
    {
        var start = DateTime.Parse((timesheet.DateAdded + timesheet.StartTime).ToString());
        var finished = DateTime.Parse((timesheet.DateCompleted + timesheet.EndTime).ToString());
        DateTime.TryParse(timesheet.RelevantDate.ToString(), out DateTime relevant);

        model.Add(new InvoiceTimesheetViewModel
        {
            RelevantDate = relevant,
            BillableHours = timesheet.BillableHours,
            Finished = finished,
            Id = timesheet.Id,
            StaffMember = timesheet.StaffMember.UserName, // NRE here.
            Start = start,
            Task = timesheet.Task.Name // NRE here.
        });
    }
    return model;
}

為了解決這些問題,我不得不將獲取數據的查詢更改為以下內容:

var timesheets = db.Timesheets.Include(i => i.StaffMember).Include(i => i.Task)
            .Where(x => x.Approved && x.Company.Id == companyId && !x.Deleted).ToList();

為什么實體框架有時很樂意在沒有我明確請求該數據的情況下為我提供數據,有時又需要我明確地請求該數據,否則拋出錯誤?

我怎么知道什么時候需要顯式包含要查找的數據,什么時候不包含?

實體框架使用延遲加載來加載子關系。 為了使延遲加載正常工作,模型中的屬性應標記為virtual關鍵字。 Ef會覆蓋它並添加延遲加載支持。

當您沒有虛擬屬性時,EF無法稍后再加載子關系數據,因此只有在這種情況下才可以這樣做-在使用Include加載初始數據期間。

public class Timesheet
{
    ...
    public virtual StaffMember StaffMember { get; set; }
    public virtual Task Task { get; set; }
    ...
}

這取決於您的模型。 如果您已將關系屬性標記為virtual則需要使用.Include以便EF知道您需要它。 這是延遲加載。 保留機器的內存和數據庫請求。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM