【问题标题】:Cloning entity with EF 6, null reference exception使用 EF 6 克隆实体,空引用异常
【发布时间】:2014-11-30 13:29:11
【问题描述】:

我正在尝试使用以下技术克隆一个实体(EF 6.x,代码优先):Entity Framework 5 deep copy/clone of an entity

但是,在尝试将克隆的票证添加到 DbSet 时,我得到了一个奇怪的 NullReference 异常:

var clonedTicket = _context.Tickets
          .AsNoTracking()
          .Include(o => o.Lines.Select(l => l.Serials))
          .Include(o => o.Payments.Select(p => p.PayCodeInfo))
          .SingleOrDefault(o => o.TicketId == ticketId);

clonedTicket.TicketId = _context.Tickets.Max(o => o.TicketId) + 1;

foreach (var line in clonedTicket.Lines)
    line.TicketId = clonedTicket.TicketId;

foreach (var payment in clonedTicket.Payments)
    payment.TicketId = clonedTicket.TicketId;

  _context.Tickets.Add(clonedTicket);  <---- System.NullReferenceException
  _context.SaveChanges();

例外是 _context.Tickets.Add(clonedTicket)。

clonedTicket 看起来完全正常,没有什么是不应该的。当然,_context 和 Tickets(DbSet)都是非空的。

这里是完整的例外:

System.NullReferenceException was unhandled by user code
  HResult=-2147467261
  Message=Object reference not set to an instance of an object.
  Source=EntityFramework
  StackTrace:
       at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.MarkForeignKeyPropertiesModified()
       at System.Data.Entity.Core.Objects.DataClasses.EntityReference.AddToNavigationPropertyIfCompatible(RelatedEnd otherRelatedEnd)
       at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.IncludeEntity(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach)
       at System.Data.Entity.Core.Objects.DataClasses.EntityCollection`1.Include(Boolean addRelationshipAsUnchanged, Boolean doAttach)
       at System.Data.Entity.Core.Objects.DataClasses.RelationshipManager.AddRelatedEntitiesToObjectStateManager(Boolean doAttach)
       at System.Data.Entity.Core.Objects.ObjectContext.AddObject(String entitySetName, Object entity)
       at System.Data.Entity.Internal.Linq.InternalSet`1.<>c__DisplayClassd.<Add>b__c()
       at System.Data.Entity.Internal.Linq.InternalSet`1.ActOnSet(Action action, EntityState newState, Object entity, String methodName)
       at System.Data.Entity.Internal.Linq.InternalSet`1.Add(Object entity)
       at System.Data.Entity.DbSet`1.Add(TEntity entity)
       at TheRepo.CreateCloneFromTicket(Int32 ticketId, String clientIp) in c:\...\TheRepo.cs:line 23
       at TheController.CreateReturn(Int32 ticketId) in c:\...\TheController.cs:line 232
       at lambda_method(Closure , Object , Object[] )
       at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)
       at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)
       at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)
  InnerException: 

我在这里错过了什么?

【问题讨论】:

  • clonedTicket 所包含的实体之间是否存在空关系?
  • 查看堆栈跟踪,似乎被克隆对象的Lines 或Payments 属性为空。
  • @Alireza Lines 和 Payments 都已填充(如果没有填充,前面的 foreach 循环将引发异常)。
  • @Tim 我已经检查并仔细检查了这一点,但我没有看到任何空关系。 Lines 和 Payments 都已填充,它们的关系也是如此。事实上,整个对象图中唯一为 null 的属性是工单行中可以为空的注释字段。
  • @Lars335 你是对的。对不起。还是很奇怪

标签: c# entity-framework


【解决方案1】:

我得到了这个工作。诀窍是在检索实体之前设置 ProxyCreationEnabled = false:

_context.Configuration.ProxyCreationEnabled = false;
var returnTicket = _context.Tickets
   .AsNoTracking()
   .Include(o => o.Lines.Select(l => l.Serials))
   .Include(o => o.Payments)
   .SingleOrDefault(o => o.TicketId == ticketId);
_context.Configuration.ProxyCreationEnabled = true;

我不能说我完全理解为什么会这样,但我想这与启用 ProxyCreation 时 EF 所做的延迟加载有关(我在这里不需要/不想要,因为我正在显式加载相关实体)。

【讨论】:

  • 这对我修复这个晦涩的错误非常有帮助。你应该接受你自己的答案。
猜你喜欢
  • 1970-01-01
  • 2018-09-13
  • 1970-01-01
  • 2017-11-17
  • 2020-03-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多