在实体框架 6 中延迟加载数据,MySql 不起作用

本文关键字:数据 MySql 不起作用 延迟加载 实体 框架 | 更新日期: 2023-09-27 18:34:22

我正在使用MySql开发一个代码优先的EF6项目。我已经设置了数据类,以便它们的相关数据对象应该是延迟加载的,但是每次调用它们时它们似乎运行得非常慢。

这是我的一个实体类的示例:

[Table("Carrier")]
public class DBCarrier
{
    [Key]
    [Column("CarrierId")]
    public int carrierId { get; set; }
    [MaxLength(128), Required]
    public string CarrierName { get; set; }
    public virtual ICollection<DBDepot> Depots { get; set; }
    public virtual ICollection<DBZone> Zones { get; set; }
}

但是当我像这样对此类的对象调用Zones时(这都在一个语句中,但我将其分开以尝试找出问题所在(:

ICollection<DBZone> zones = carrier.Zones;
IEnumerable<DBZone> zones1 = zones.Where(x => x.Postcode == postcode);
return zones.Select(x => x.ZoneName).FirstOrDefault();

每次我打电话carrier.Zones大约需要 8 秒才能运行。我认为通过将zones定义为 ICollection 会延迟数据库查询的执行。

在实体框架 6 中延迟加载数据,MySql 不起作用

ICollection表示数据肯定已经在内存中具体化了。获得所需行为的唯一方法是使用支持延迟执行的接口,并且只有两个:

  • IQueryable 查询是使用 Expressions 构建的,用于对远程数据源(例如 SQL 数据库(触发查询。
  • IEnumerable 查询是使用 Delegates 构建的,用于对内存中已有的数据集触发查询。

使用这两种接口类型中的任何一种都会导致在使用 First()FirstOrDefault()ToList()ToArray() 迭代数据时执行查询。

但是看到您只需要查询的区域名称是非常低效的。你获取整个DBZone对象,但你只取名,我建议只取名:

return carrier.Zones.FirstOrDefault(z => z.Postcode == postcode).Select(z => z.ZoneName);

为此,您当然需要carrier作为IQueryable

编辑:刚刚注意到"每次我打电话给运营商。区域运行大约需要 8 秒。

这是延迟加载的预期行为。当您访问数据库时,数据将从数据库中获取 => 运营商的数据库调用,以及访问区域时对数据库的另一个调用。使用预先加载(Include方法(在一次访问数据库时获取所有所需数据可以避免这种情况。