【问题标题】:Is it possible to modify entity object within ObjectStateManagerChanged handler?是否可以在 ObjectStateManagerChanged 处理程序中修改实体对象?
【发布时间】:2011-08-23 17:19:06
【问题描述】:

这是我需要实现的业务逻辑:

数据模型中有多种实体类型,例如:User、UserProfile、UserProfileValue、UserExtendedData 等。

当创建像用户这样的实体时,我需要自动创建逻辑链接的其他实体(通常在 db 中具有 1:1 关系),例如 UserProfile。

每个实体都有一个带有 OnCreating/OnCreated、OnUpdating/OnUpdated 方法的控制器,这些方法是从我的数据上下文类的重写 SaveChanges 方法中调用的。

public override int SaveChanges(SaveOptions options)
{
    IEnumerable<ObjectStateEntry> addedEntities = ObjectStateManager.GetObjectStateEntries(EntityState.Added);
    IEnumerable<ObjectStateEntry> changedEntities = ObjectStateManager.GetObjectStateEntries(EntityState.Modified);
    IEnumerable<ObjectStateEntry> deletedEntities = ObjectStateManager.GetObjectStateEntries(EntityState.Deleted);

    InvokeSavingControllers(addedEntities, changedEntities, deletedEntities);

    //some other code

    int rowsAffected = base.SaveChanges(options);

    InvokeSavedControllers(addedEntities, changedEntities, deletedEntities);

    return rowsAffected;
}

如果我在 User.OnCreating() 方法中实现了自动创建,那么最终不会为所有自动创建的子实体调用 OnCreating() 控制器,因为集合 addedEntities 不会使用新条目进行更新。

我的一个想法是通过处理数据上下文的ObjectStateManagerChanged 来执行依赖实体的自动创建

private void ObjectStateManagerObjectStateManagerChanged(object sender, System.ComponentModel.CollectionChangeEventArgs e)
{
    if (e.Action == CollectionChangeAction.Add)
    {
        var state = ObjectStateManager.GetObjectStateEntry(e.Element).State;
        if (state == EntityState.Added)
        {
            //should call on creating handlers
            if (e.Element is User)
            {
                User user = (User)e.Element;
                user.UserProfile = UserProfile.CreateDefaultProfile();
            }
        }
    }
}

但不幸的是,如果我这样做,我会收到 NullReference 异常。即使我尝试在ObjectStateManagerObjectStateManagerChanged 中修改用户的属性,我也会遇到异常。

关于如何实现所需功能的任何想法或建议?

编辑:

我得到的空引用:

System.NullReferenceException was unhandled by user code
  Message=Object reference not set to an instance of an object.
  Source=System.Data.Entity
  StackTrace:
       at System.Data.Objects.ObjectContext.AddSingleObject(EntitySet entitySet, IEntityWrapper wrappedEntity, String argumentName)
       at System.Data.Objects.ObjectContext.AddObject(String entitySetName, Object entity)
       at Edm.Entity.Entities.AddObject(Object entity) 

Edm.Entity.Entities.AddObject(Object entity) 是将新的 User 对象添加到上下文的位置。

EDIT2: 不知道我改变了什么,但与上面相同的代码开始抛出以下异常:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
  <code></code>
  <message xml:lang="en-US">An error occurred while processing this request.</message>
  <innererror>
    <message>Object reference not set to an instance of an object.</message>
    <type>System.NullReferenceException</type>
    <stacktrace>   at System.Data.Objects.DataClasses.EntityReference`1.Exclude()&#xD;
   at System.Data.Objects.DataClasses.RelationshipManager.RemoveRelatedEntitiesFromObjectStateManager(IEntityWrapper wrappedEntity)&#xD;
   at System.Data.Objects.ObjectContext.AddObject(String entitySetName, Object entity)&#xD;
   at System.Data.Services.Providers.ObjectContextServiceProvider.CreateResource(String containerName, String fullTypeName)&#xD;
   at System.Data.Services.UpdatableWrapper.CreateResource(String containerName, String fullTypeName)&#xD;
   at System.Data.Services.Serializers.SyndicationDeserializer.CreateObject(SegmentInfo segmentInfo, Boolean topLevel, SyndicationItem item)&#xD;
   at System.Data.Services.Serializers.SyndicationDeserializer.CreateSingleObject(SegmentInfo segmentInfo)&#xD;
   at System.Data.Services.Serializers.Deserializer.ReadEntity(RequestDescription requestDescription)&#xD;
   at System.Data.Services.Serializers.Deserializer.HandlePostRequest(RequestDescription requestDescription)&#xD;
   at System.Data.Services.DataService`1.HandlePostOperation(RequestDescription description, IDataService dataService)&#xD;
   at System.Data.Services.DataService`1.ProcessIncomingRequest(RequestDescription description, IDataService dataService)&#xD;
   at System.Data.Services.DataService`1.BatchDataService.HandleBatchContent(Stream responseStream)</stacktrace>
  </innererror>
</error>

【问题讨论】:

  • 你从哪里得到`NullReference 异常`?

标签: c# .net entity-framework entity-framework-4


【解决方案1】:

我也有同样的问题。在 ObjectStateManagerChanged 事件期间添加另一个 EntityObject 似乎是一个问题。奇怪的是我的代码(可能还有你的代码)在 .net 3.5 中运行良好,但在 4.0 中给出了 NullReferenceException。

我已经调试了 .net 框架,并发现它在调用 ObjectStateManagerChanged 事件后在内部 ObjectContext.AddSingleObject 方法中崩溃。发生此异常的原因是内部 ProcessedEntities 哈希集在公共 AddObject 方法的末尾设置为空。但是,如果在 ObjectStateManagerChanged 事件期间创建了 EntityObject,则不应将此哈希集设为 null。

这似乎是 .net framework 4.0 的错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-21
    • 2021-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多