Breeze-在保存之前,根据实体的导航属性在服务器上修改实体 [英] breeze - modify an entity, on the server, based upon it's navigational properties, before saving

查看:0
本文介绍了Breeze-在保存之前,根据实体的导航属性在服务器上修改实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法在服务器端的Breeze中获取BeForeSaveEntity(或保存前的任何其他位置)中实体的导航属性的"Current"值?我所说的Current指的是数据库中存在的内容,以及合并进来的任何更改。这不是用来验证的,而是基于父字段和子字段来计算父属性的值(我不想在客户机上使用)...

例如

public class Parent {
  public ICollection<Child> Children{ get; set; }
}

。。。

protected override bool BeforeSaveEntity(EntityInfo entityInfo) {
  if (entityInfo.Entity.GetType() == typeof(Parent) &&
  (entityInfo.EntityState == EntityState.Added || entityInfo.EntityState == EntityState.Updated)) {

   // Lazy load Parent's Children collection out of breeze's context 
   // so items are "current' (existing merged with changes)

   Parent parent = (Parent)entityInfo.Entity;
   Context.Entry(parent).Collection(p => p.Children).Load();

   // this throws exception Member 'Load' cannot be called for property
   // 'Children' because the entity of type 'Parent' does not exist in the context.
  }
}  

我认为它们还不在DBContext中。我所能想到的就是从数据库中检索现有的子项,然后手动合并BeForeSaveEntities中的更改,这是一件麻烦的事情。

推荐答案

在Breeze用于保存的DbContext中未启用延迟加载。具体原因见this SO answer

您应该在separate DbContext中加载任何其他实体。


这里有一个我如何在项目中做到这一点的例子。也许应该将MergeEntities和DetachEntities方法包括在Breeze中,以简化此操作。

protected override Dictionary<Type, List<EntityInfo>> BeforeSaveEntities(Dictionary<Type, List<EntityInfo>> saveMap)
{
    // create a separate context for computation, so we don't pollute the main saving context
    using (var newContext = new MyDbContext(EntityConnection, false))
    {
        var parentFromClient = (Parent)saveMap[typeof(Parent)][0].Entity;

        // Load the necessary data into the newContext
        var parentFromDb = newContext.Parents.Where(p => p.ParentId == parentFromClient.ParentId)
            .Include("Children").ToList();

        // ... load whatever else you need...

        // Attach the client entities to the ObjectContext, which merges them and reconnects the navigation properties
        var objectContext = ((IObjectContextAdapter)newContext).ObjectContext;
        var objectStateEntries = MergeEntities(objectContext, saveMap);

        // ... perform your business logic...

        // Remove the entities from the second context, so they can be saved in the original context
        DetachEntities(objectContext, saveMap);
    }
    return saveMap;
}

/// Attach the client entities to the ObjectContext, which merges them and reconnects the navigation properties
Dictionary<ObjectStateEntry, EntityInfo> MergeEntities(ObjectContext oc, Dictionary<Type, List<EntityInfo>> saveMap)
{
    var oseEntityInfo = new Dictionary<ObjectStateEntry, EntityInfo>();
    foreach (var type in saveMap.Keys)
    {
        var entitySet = this.GetEntitySetName(type);
        foreach(var entityInfo in saveMap[type])
        {
            var entityKey = oc.CreateEntityKey(entitySet, entityInfo.Entity);
            ObjectStateEntry ose;
            if (oc.ObjectStateManager.TryGetObjectStateEntry(entityKey, out ose))
            {
                if (ose.State != System.Data.Entity.EntityState.Deleted)
                    ose.ApplyCurrentValues(entityInfo.Entity);
            }
            else
            {
                oc.AttachTo(entitySet, entityInfo.Entity);
                ose = oc.ObjectStateManager.GetObjectStateEntry(entityKey);
            }

            if (entityInfo.EntityState == Breeze.ContextProvider.EntityState.Deleted)
            {
                ose.Delete();
            }
            oseEntityInfo.Add(ose, entityInfo);
        }
    }
    return oseEntityInfo;
}

/// Remove the entities in saveMap from the ObjectContext; this separates their navigation properties
static void DetachEntities(ObjectContext oc, Dictionary<Type, List<EntityInfo>> saveMap)
{
    foreach (var type in saveMap.Keys)
    {
        foreach (var entityInfo in saveMap[type])
        {
            try
            {
                oc.Detach(entityInfo.Entity);
            }
            catch
            { // the object cannot be detached because it is not attached
            }
        }
    }
}

这篇关于Breeze-在保存之前,根据实体的导航属性在服务器上修改实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆