带有延迟加载的 EF Core:NotImplementedException:'这是一个 DynamicProxy2 错误:拦截器尝试“继续”方法

问题描述 投票:0回答:2

我的简单代码行

Db.CoverageParts.Add(newPart);
在启用了延迟加载的情况下引发了 EF Core 5.0.6 / Castle 4.4.1 的以下异常:

System.NotImplementedException
  HResult=0x80004001
  Message=This is a DynamicProxy2 error: The interceptor attempted to 'Proceed' for method 'Microsoft.EntityFrameworkCore.Infrastructure.ILazyLoader get_LazyLoader()' which has no target. When calling method without target there is no implementation to 'proceed' to and it is the responsibility of the interceptor to mimic the implementation (set return value, out arguments etc)
  Source=Castle.Core
  StackTrace:
   at Castle.DynamicProxy.AbstractInvocation.ThrowOnNoTarget()
   at Castle.DynamicProxy.Internal.CompositionInvocation.EnsureValidTarget()
   at Castle.Proxies.Invocations.IProxyLazyLoader_get_LazyLoader.InvokeMethodOnTarget()
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.DynamicProxy.StandardInterceptor.PerformProceed(IInvocation invocation)
   at Castle.DynamicProxy.StandardInterceptor.Intercept(IInvocation invocation)
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.Proxies.MLCoveragePartProxy.get_LazyLoader()
   at Microsoft.EntityFrameworkCore.Metadata.Internal.ClrPropertyGetter`2.GetClrValue(Object entity)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetProperty(IPropertyBase propertyBase, Object value, Boolean isMaterialization, Boolean setModified, Boolean isCascadeDelete, CurrentValueType valueType)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetProperty(IPropertyBase propertyBase, Object value, Boolean isMaterialization, Boolean setModified, Boolean isCascadeDelete)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetServiceProperties(EntityState oldState, EntityState newState)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges, Boolean modifyProperties)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState, Boolean acceptChanges, Boolean modifyProperties, Nullable`1 forceStateWhenUnknownKey)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.PaintAction(EntityEntryGraphNode`1 node)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode`1 node, Func`2 handleNode)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.AttachGraph(InternalEntityEntry rootEntry, EntityState targetState, EntityState storeGeneratedWithKeySetTargetState, Boolean forceStateWhenUnknownKey)
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.SetEntityState(InternalEntityEntry entry, EntityState entityState)
   at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.Add(TEntity entity)
   at --- SNIP THIS IS WHERE MY CODE APPEARS IN THE CALL STACK ---

这是一个大型项目,正在从 .NET Framework 4.8 升级到 .NET Core 5。EF Core 中启用了延迟加载。到目前为止,该项目中 97% 的代码已升级、测试并验证工作正常,没有任何问题。

我正在努力使用简化的代码重现此问题,但要产生此问题还有很多工作要做。到目前为止,我已经验证此问题发生在我的代码的简单单线程版本中,几乎没有使用 async/await。整个应用程序中的类似代码可以正常运行。

所有库均已检查为 .NET、EF Core 和 Castle 的最新 RTM 版本(尽管后者只是 EF Core 代理的依赖项)。

任何人都可以提供任何可能给我攻击途径的指示吗?

entity-framework entity-framework-core castle-windsor ef-core-5.0
2个回答
2
投票

我突然意识到,尝试访问刚刚创建的实体上的 LazyLoader 属性是没有意义的,更不用说失败了。当然,它还没有绑定到上下文,LazyLoader 应该为 null,对吗??

事实上,真正的问题是新类型是动态代理,而不是具体的 POCO。问题源于新实体的创建方式。因为它是从相同类型的现有实体的实例克隆的派生类型,所以我的代码执行以下操作:

var newCoveragePart = (CoveragePart)Activator.CreateInstance(oldCoveragePart.GetType());

问题当然是,这克隆了一个代理,而不是基本类型,我认为这会给所有事情带来麻烦。这种做法在 .NET Framework 的 EF 中运行良好,因此当意识到它在 EF Core 中不起作用时有点令人震惊。以下是解决该问题所需的内容:

var cpType = (oldCoveragePart is IProxyLazyLoader ? oldCoveragePart.GetType().BaseType : oldCoveragePart.GetType()); 
var newCoveragePart = (CoveragePart)Activator.CreateInstance(cpType);

旁注:我还使用 AutoMapper 浅克隆实体,并在执行此操作后将它们添加到上下文中。我将不得不检查该代码以确保它没有相同或相似的问题。


0
投票

就我而言,我忘记告诉 EF Core 有一个新的关系,但仍将外键和虚拟实体添加到业务逻辑中。因此,当它尝试根据外键拉取实体时,惰性加载程序失败并给出了相同的错误。

我有一个

organization
createdBy
关系,其中创作者是
ApplicationUser
。这是添加的内容:

protected override void OnModelCreating(ModelBuilder builder)
{
      builder.Entity<Organization>()
          .HasOne(o => o.CreatedBy)
          .WithMany()
          .HasForeignKey("CreatedById")
          .IsRequired(false)
          .OnDelete(DeleteBehavior.Restrict);
}

以下组织实体:

public class Organization: Entity
{
    public string Name { get; set; }
    public string CommercialRegistration { get; set; }
    public DateTime ContractStartDate { get; set; }
    public DateTime ContractEndDate { get; set; }
    // New "CreatedBy" relationship
    public int? CreatedById { get; set; }
    public virtual ApplicationUser CreatedBy { get; set; }
}

之后,AutoMapper 能够使用惰性加载器将用户的属性映射回来。

© www.soinside.com 2019 - 2024. All rights reserved.