EF Core Eager加载嵌套集合 [英] EF Core Eager Loading nested collections

查看:216
本文介绍了EF Core Eager加载嵌套集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在Entity Framework Core中加载相关的模式,但是由于某些原因,当我在 Include()致电。

I'm trying to load a related modal in Entity Framework Core but for some reason there's a nested collection being loaded when I haven't asked for it in my Include() call.

这是我的两个型号-

Driver.cs

public partial class Driver : IBaseEntity
{
    public short DriverId { get; set; }
    public string Surname { get; set; }
    public string Initials { get; set; }
    public byte DriverStatusTypeId { get; set; }

    public DriverStatusType DriverStatusType { get; set; }
}

DriverStatusType.cs

public partial class DriverStatusType
{
    public DriverStatusType()
    {
        Drivers = new HashSet<Driver>();
    }

    public byte DriverStatusTypeId { get; set; }
    public string DriverStatusTypeName { get; set; }
    public string Description { get; set; }

    public ICollection<Driver> Drivers { get; set; }
}

DriversService.cs

public class DriverService : IDriverService
{
    public DriverService(MyContext context)
    {
        Context = context;
    }

    public MyContext Context { get; }

    public async Task<IEnumerable<Driver>> GetAllDrivers()
    {
        var drivers = await Context
            .Drivers
            .Include(d => d.DriverStatusType)
            .toListAsync();

        return drivers;
    }

    public async Task<Driver> GetDriverById(int id)
    {
        var driver = await Context
            .Drivers
            .Include(d => d.DriverStatusType)
            .Where(d => d.DriverId == id)
            .FirstOrDefaultAsync();

        return driver;
    }
}

现在我叫从控制器获取GetDriverById(int id)方法我得到了我期望的结果-

Now when I call the GetDriverById(int id) method from my controller I get back what I'm expecting -

{
    "driverId": 1,
    "surname": "Stark",
    "initials": "T",
    "driverStatusTypeId": 2,
    "driverStatusType": {
        "driverStatusTypeId": 2,
        "driverStatusTypeName": "Available",
        "description": "This driver is available",
        "drivers": []
    }
}

但是 GetAllDrivers() 方法返回嵌套的 drivers 集合,这意味着我要返回的数据非常大-

However the GetAllDrivers() method is returning the nested drivers collection which means the data I'm getting back is huge -

[
    {
        "driverId": 1,
        "surname": "Stark",
        "initials": "T",
        "displayText": "Tony Stark",
        "driverStatusTypeId": 2,
        "driverStatusType": {
            "driverStatusTypeId": 2,
            "driverStatusTypeName": "Available",
            "description": "This driver is available",
            "drivers": [
                {
                    "driverId": 2,
                    "surname": "Rogers",
                    "initials": "S",
                    "driverStatusTypeId": 2
                },
                {
                    "driverId": 3,
                    "surname": "Romanoff",
                    "initials": "N",
                    "driverStatusTypeId": 2
                },
                {
                    "driverId": 4,
                    "surname": "Banner",
                    "initials": "B",
                    "driverStatusTypeId": 2
                },
                ...

我认为热切加载的想法仅包括您指定的相关模型在包含语句中,但它看到ms事实并非如此。有人可以解释这里发生了什么吗?

I thought the idea of eager loading was to only include the related models you specify in the include statement but it seems this is not the case. Could someone explain what's happening here?

推荐答案


我认为渴望加载的想法只包括了您在include语句中指定的相关模型,但事实并非如此。有人可以解释这里发生了什么吗?

I thought the idea of eager loading was to only include the related models you specify in the include statement but it seems this is not the case. Could someone explain what's happening here?

您是对的,事实并非如此。急切加载的想法是确保您指定的相关数据已加载。这并不意味着/保证不包含相关数据

You are right, that's not the case. The idea of eager loading is to ensure the related data you specify is loaded. It doesn't mean/guarantee that related data won't be included.

加载EF Core文档的相关数据部分:


提示

Entity Framework Core会将导航属性自动修复为其他任何属性先前已加载到上下文实例的实体。因此,即使您未明确包含导航属性的数据,如果先前已加载某些或所有相关实体,也可能仍会填充该属性。

Entity Framework Core will automatically fix-up navigation properties to any other entities that were previously loaded into the context instance. So even if you don't explicitly include the data for a navigation property, the property may still be populated if some or all of the related entities were previously loaded.

导航属性修复意味着在实体实例实现时,所有相关的导航属性都会更新以反映它,例如,将 Driver 添加到 Driver.DriverStatusType.Drivers ,反之亦然。

The navigation property fix-up means that anytime entity instance is materialized, all related navigation properties are updated to reflect it, for instance Driver is added to Driver.DriverStatusType.Drivers and vice versa.

请注意,在使用跟踪查询时,这可能会发生 之后,实现非包含查询( ToList()),因为更改跟踪器会跟踪对象引用并在您执行其他跟踪查询时自动更新它们。

Note that when using tracking queries, this might happen after the non including query is materialized (ToList()) because change tracker keeps track of object references and automatically updates them when you perform other tracking queries.

该修正过程的另一个效果是,当您包含关系的一端时,另一端的反向导航属性将自动填充。

Another effect of that fix-up process is that when you include one of the ends of the relationship, the inverse navigation property of the other end is automatically populated.

因此,即使第一种情况是 Drivers 属性应填充并包含单个项目。这就是我的干净测试中实际发生的事情,不知道您为什么会有所不同-可能是序列化程序将其隐藏了?

So even if the first case the Drivers property should be populated and contain single item. And this is what actually happening in my clean tests, don't know why you are getting difference - may be the serializer is hiding it?

无论如何,这一切都意味着您实际上无法控制导航属性的内容。可以精确控制返回的唯一方法是使用特殊的DTO / ViewModel等类和投影( Select )。

Anyway, all that means that you can't really control the content of the navigation properties. The only way you can control exactly what are you returning is to use special DTO/ViewModel etc. classes and projection (Select).

这篇关于EF Core Eager加载嵌套集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆