尽管代理被禁用,实体框架会自动设置关系

Posted

技术标签:

【中文标题】尽管代理被禁用,实体框架会自动设置关系【英文标题】:Entity Framework automatically sets relationship although proxies are disabled 【发布时间】:2017-12-06 20:31:09 【问题描述】:

我在理解 Entity Framework 如何为内存中的实体连接实体关系时遇到了一些麻烦。

要使用实体框架进行查询,我禁用了代理创建和延迟加载:

public static CoreContext GetReadCoreContext()

    var context = GetCoreContext();
    context.Configuration.ProxyCreationEnabled = false;
    context.Configuration.LazyLoadingEnabled = false;
    return context;

由于我在 ER 模型中有一些继承类型,并且我只想在继承类型是特定类型时才包含一些实体,因此我需要执行两个单独的查询。只有特定类型包含与本地化的关系。请注意,这只是为了说明为什么我必须进行两个单独的查询,并且不一定与我努力理解 Entity Framework 的机制有关。

首先查询通用部分,不依赖于具体类型:

var myGuid = Guid.Parse("6a81de0b-ce4b-44dc-a693-ca4e13e7d2ab");

using (var ctx = ContextFactory.GetReadCoreContext(TenantId))

    var entitiesQuery = ctx.MyEntity
        .Include(i => i.EntityA)
        .Include(i => i.GeneralType);

    var myEntity = entitiesQuery.FirstOrDefault(e => e.Id == myGuid);

    // check if myEntity.GeneralType is of the specialized type then query depending on the properties of this type

    var specificEntity = myEntity.GeneralType as SpecificType;
    if (specificEntity != null) 
    
        var myLocalization = ctx.Localizations.Where(l => l.Id == specificEntity.LocalizationId)

        // Entity Framework is automatically setting myEntity.Localization to myLocalization
    

我不明白的是,Entity Framework 如何附加/设置内存对象的关系。请注意,内存中的对象不是代理 - 否则我会理解为什么会这样。

当我使用.AsNoTracking() 时,上述行为不起作用。

【问题讨论】:

我认为您误解了延迟加载的含义。禁用它意味着当您访问不在上下文中的导航属性时,EF 不会自动额外访问数据库(因为它没有被Include 急切加载,或通过查询显式获取)。但是如果该导航属性中的实体已经在上下文中(因为它之前已经被查询并附加到上下文中)你会看到它,因为 EF 知道实体之间的关系,并且导航属性只是一个参考到上下文中的实体。 关于代理,如果启用延迟加载,则必须启用它们,但是在某些情况下您启用代理并禁用延迟加载。代理与跟踪实体状态有关。 Here 你可以找到ProxyCreationEnabledLazyLoadingEnabled 组合值的解释。 也许您想发表您的评论作为答案,以便我将其标记为解决方案。真的帮助我解决了我的理解问题。 【参考方案1】:

我认为您误解了延迟加载的含义。禁用它意味着当您访问不在上下文中的导航属性时,EF 不会自动额外访问数据库(因为它没有被Include 急切加载,或通过查询显式获取)。但是如果该导航属性中的实体已经在上下文中(因为它之前已经被查询并附加到上下文中)你会看到它,因为 EF 知道实体之间的关系,并且导航属性只是一个参考到上下文中的实体。

关于代理,如果启用延迟加载,则必须启用它们,但在某些情况下您启用代理并禁用延迟加载。代理与跟踪实体状态有关。 Here你可以找到ProxyCreationEnabledLazyLoadingEnabled组合值的解释

【讨论】:

另请注意,此“关系修复”是 EF 更改跟踪器的一项功能。如果您禁用查询的更改跟踪,它将禁用此行为。

以上是关于尽管代理被禁用,实体框架会自动设置关系的主要内容,如果未能解决你的问题,请参考以下文章

我应该使用实体框架 4.1 和 MVC3 启用或禁用动态代理吗?

如果我在实体框架中全局禁用 ProxyCreation 会有啥后果?

powershell 实现自动IE代理设置

设置可选:必需的关系实体框架 - 流式 API

实体框架 6:在上下文中禁用跟踪时更新实体

禁用实体框架的默认值生成(代码优先)