简体   繁体   English

实体框架6懒加载奇怪

[英]Entity framework 6 lazy loading oddity

I have a poco class which is wired up to the entity framework. 我有一个连接到实体框架的poco类。 The class is called PersonalizationCatalogPrice. 该类称为PersonalizationCatalogPrice。 This class has a sub object called Pricelevel which does not have the virtual keyword on it. 这个类有一个名为Pricelevel的子对象,它没有虚拟关键字。 Because of this (based on my understanding) this object should never lazy load and should return null. 因为这(基于我的理解)这个对象永远不应该延迟加载,应该返回null。 However, we have found that this object seems to load up when used in a specific manner. 但是,我们发现当以特定方式使用时,此对象似乎会加载。

so the basic class structure is this 所以基本的类结构是这样的

public class PersonalizationCatalogPrice
    {
        public int PersonalizationCatalogPriceID { get; set; }

        public int PersonalizationCatalogId { get; set; }

        public virtual PersonalizationCatalog PersonalizationCatalog { get; set; }

        public decimal CustomerRetail { get; set; }

        public decimal ConsultantCost { get; set; }

        public decimal PersonalVolume { get; set; }

        public decimal QualifyingVolume { get; set; }

        public int PriceLevelId { get; set; }

        public PriceLevel PriceLevel { get; set; }
}

Here is an example. 这是一个例子。 In the first line we return an Iqueryable of PersonalizationCatalogPrice items. 在第一行中,我们返回Iqueryable of PersonalizationCatalogPrice项。 In the second line we have another IQueryable and we are using the priclevel object in this iQueryable (see the line "contains pcp.pricelevel"). 在第二行中,我们有另一个IQueryable,我们在这个iQueryable中使用了priclevel对象(参见“contains pcp.pricelevel”行)。 When we do this, the pricelevel object loads up even though it has no virtual keyword. 当我们这样做时,即使没有虚拟关键字,pricelevel对象也会加载。

IQueryable<PersonalizationCatalogPrice> allPersPriceRecords = _e2ReposMan.PersonalizationRepository.GetSomeRecords();

//List<PersonalizationCatalogPrice> persprices = allPersPriceRecords.ToList();

var persQuery = from pl in personalizationLines
                join pcp in allPersPriceRecords on pl.Item2.PersonalizationCatalogPriceID equals pcp.PersonalizationCatalogPriceID
                where !HostessPriceLevelTypes().Contains(pcp.PriceLevel.PriceLevelTypeId)
                select pl.Item2.PersonalVolume * pl.Item1;

var openOrdersTotal = (query.Any() ? query.Sum() : 0) + (persQuery.Any() ? persQuery.Sum() : 0);

Modifying this code by uncommenting the second line which performs a ToList() however. 通过取消注释执行ToList()的第二行来修改此代码。 Makes the pricelevel subobject return null as expectedd since it does not have a virtual keyword on it and the entity framework then works as we anticipate. 使pricelevel子对象按预期返回null,因为它上面没有虚拟关键字,然后实体框架按预期工作。 (EF 6) (EF 6)

Does anyone know why we are able to load the pricelevel property when we do not do the toList(). 有没有人知道我们为什么能够在不执行toList()时加载pricelevel属性。

thanks for any assistance. 谢谢你的帮助。

Based on the wording you used, it appears that you expect the PriceLevel property to be null when not using lazy loading. 根据您使用的措辞,在不使用延迟加载时,您似乎期望PriceLevel属性为null

There are some cases i can think of, in which this expectation would not be met. 在某些情况下我可以想到,这种期望不会得到满足。

The first case would be if you are loading the data in a eager way. 第一种情况是,如果您以急切的方式加载数据。 Which would be explicitly using Include() . 哪个将明确使用Include() This behaviour is also called eager loading. 此行为也称为急切加载。 Since eager loading does load everything it is allowed to, it does not require you to enumerate the collection by calling ToArray() or ToList() or other methods that trigger enumeration. 由于急切加载确实加载了允许的所有内容,因此不需要通过调用ToArray()ToList()或其他触发枚举的方法来枚举集合。 Every property which is not lazy will be loaded, that includes all its value type properties and non-lazy properties. 将加载每个非延迟属性,包括其所有值类型属性和非延迟属性。

Your code does not indicate this, however the property would still not be null if you did this on the same DbContext derived instance before executing the code you displayed. 您的代码不会指明这一点,但是如果您在执行显示的代码之前在同一个DbContext派生实例上执行此操作,则该属性仍然不为null。 This would happen whenever the entity in question already resides cached in your DbContext. 只要有问题的实体已经在您的DbContext中缓存,就会发生这种情况。

The same would be true if you had loaded that entity explicitly by calling Load() or if it had been returned from some other previous query. 如果您通过调用Load()显式加载了该实体,或者它是从其他先前的查询返回的,那么情况也是如此。

In order to verify whether this is the case or not you can use the AsNoTracking() extension method. 为了验证是否是这种情况,您可以使用AsNoTracking()扩展方法。 Entities which are not tracked will, among other effects, not be linked with each other. 除了其他效果之外,未跟踪的实体将不会彼此链接。

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

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