简体   繁体   English

使用MySql无法在Entity Framework 6中延迟加载数据

[英]Lazy loading data in Entity Framework 6 with MySql not working

I'm working on a code-first EF6 project using MySql. 我正在使用MySql进行代码优先EF6项目。 I have setup my data classes such that their related data objects should be lazy-loaded, but they seem to run very slowly each time they are called. 我已经设置了数据类,以使它们的相关数据对象应延迟加载,但每次调用它们时,它们的运行速度似乎都很慢。

This is an example of one of my entity classes: 这是我的实体类之一的示例:

[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; }
}

But when I call the Zones on an object of this class like this (this was all in one statement, but I separated it out to try and find out where the problem was): 但是,当我像这样在此类的对象上调用Zones时(全部在一条语句中,但是我将其分离出来以尝试找出问题所在):

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

Every time I call carrier.Zones it takes about 8 seconds to run. 每次我打电话carrier.Zones大约需要8秒运行。 I thought that by defining zones as an ICollection would delay execution of the database query. 我认为通过将zones定义为ICollection会延迟数据库查询的执行。

ICollection means the data is definitely already materialized in memory. ICollection意味着数据肯定已经在内存中实现了。 The only way to get your desired behavior is to use an interface which supports deferred execution and there's only two: 获得所需行为的唯一方法是使用支持延迟执行的接口,只有两种:

  • IQueryable the query is built up using Expressions and is used to fire queries upon remote data sources (for example sql database). IQueryable是使用Expressions构建的查询,用于在远程数据源(例如sql数据库)上触发查询。
  • IEnumerable the query is built up using Delegates and is used to fire queries upon datasets already in memory. IEnumerable查询是使用Delegates建立的,用于对内存中已有的数据集进行查询。

Using any of these 2 interface types will cause your query to be executed when you iterate the data using First() , FirstOrDefault() , ToList() or ToArray() . 当使用First()FirstOrDefault()ToList()ToArray()迭代数据时,使用这两种接口类型中的任何一种都会导致执行查询。

But seeing you only need the names of the zones your query is pretty inefficient. 但是看到您只需要查询的区域名称是非常低效的。 You fetch the whole DBZone object but you only take the name, I would suggest just fetching the names: 您获取了整个DBZone对象,但只使用了名称,我建议您仅获取名称:

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

For this you need to keep carrier as an IQueryable of course. 为此,您当然需要将carrier保留为IQueryable

Edit: Just noticed "Every time I call carrier.Zones it takes about 8 seconds to run." 编辑:刚注意到“每次我打电话给运营商。区域运行大约需要8秒钟。”

This is the expected behavior for lazy loading. 这是延迟加载的预期行为。 The data will get fetched from the database when you access it => Database call for the carrier, and another call to database for the zones when you access them. 当您访问数据时,将从数据库中获取数据=>运营商的数据库调用,访问区域时又对区域的数据库调用。 This can be avoided using eager loading ( Include method) to get all the desired data in one trip to the database. 可以使用急切加载( Include方法)在一次访问数据库中获取所有所需数据的情况下避免这种情况。

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

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