在实体框架 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 会延迟数据库查询的执行。
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
方法(在一次访问数据库时获取所有所需数据可以避免这种情况。