简体   繁体   English

您何时需要在实体框架中包括相关实体?

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

This seems arbitrary to me when I have to actually .Include() related entities and when I don't. 在我必须实际使用.Include()相关实体时,以及在我不需要时,这对我来说似乎是任意的。 In some cases, EF gives me the info for the related entities without it and in other cases, it can't do anything with the related entities because I didn't include them: 在某些情况下,EF不提供相关实体的信息给我,而在其他情况下,EF无法对相关实体做任何事情,因为我没有包括它们:

Works without .Include(); 不带.include()的作品;

This is an example where I'm loading data without .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.
    }
}

Here follows the result which includes the data for the Company associated with the invoice I'm requested: 以下是结果,其中包括与我请求的发票相关的公司数据: 在此处输入图片说明

As you can see, the information for the company definitely comes through but was not explicitly included. 如您所见,该公司的信息肯定来自但未明确包含。

Doesn't work without .Include(); 如果没有.include(),则无法使用;

Conversely, I've done some mapping to do with invoices in this same project and I got NullReferenceExceptions when fetching the related entities property values because I didn't .Include() . 相反,在同一个项目中,我已经完成了一些与发票的映射,并且在获取相关实体的属性值时会得到NullReferenceExceptions,因为我没有.Include()

This method gets all the approved timesheet entries for the specified company. 此方法获取指定公司的所有批准的时间表条目。 This viewmodel is exclusively to be used when manipulating the association of timesheet entries for an invoice (so you're invoicing based on the timesheet entries selected). 此视图模型仅在处理发票的时间表条目的关联时使用(因此,您根据选定的时间表条目进行发票)。

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 occurred in the factory that maps the timesheet entities to the viewmodel: 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;
}

To fix these, I had to change the query that fetches the data to the following: 为了解决这些问题,我不得不将获取数据的查询更改为以下内容:

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

Why is Entity Framework sometimes happy to give me data without me explicitly requesting that data and sometimes it requires me to explicitly request the data or else throws an error? 为什么实体框架有时很乐意在没有我明确请求该数据的情况下为我提供数据,有时又需要我明确地请求该数据,否则抛出错误?

And how am I to know when I need to explicitly include the data I'm looking for and when I don't? 我怎么知道什么时候需要显式包含要查找的数据,什么时候不包含?

Entity framework uses lazy loading to load child relationships. 实体框架使用延迟加载来加载子关系。 For lazy loading to work property in the model should be marked with virtual keyword. 为了使延迟加载正常工作,模型中的属性应标记为virtual关键字。 Ef overrides it and adds lazy loading support. Ef会覆盖它并添加延迟加载支持。

When you have no virtual property EF has no way to load your child relationship data later, so the only time it's possible to do - during initial data loading using Include . 当您没有虚拟属性时,EF无法稍后再加载子关系数据,因此只有在这种情况下才可以这样做-在使用Include加载初始数据期间。

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

It depends on your models. 这取决于您的模型。 If you have marked relational properties as virtual then you'll need to use .Include so EF knows that you need it. 如果您已将关系属性标记为virtual则需要使用.Include以便EF知道您需要它。 It is Lazy Loading. 这是延迟加载。 Preserves machine's memory and DB requests. 保留机器的内存和数据库请求。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM