代码之家  ›  专栏  ›  技术社区  ›  Yannick Motton

如何在CRUD场景中跟踪从可观察集合中删除的对象?

  •  5
  • Yannick Motton  · 技术社区  · 15 年前

    在我们的多层业务应用程序中, ObservableCollections 自跟踪从服务调用返回的实体。

    我们希望能够从收集客户端获取实体、添加、更新和删除它们,然后将这些更改发送到服务器端,在服务器端它们将被持久化到数据库。

    自跟踪实体,正如它们的名字所暗示的那样,跟踪它们自己的状态。 创建新的ste时,它具有添加的状态;修改属性时,它设置修改的状态;也可以具有删除的状态,但从 ObservableCollection (显然)。如果您想要这种行为,您需要自己编写代码。

    在我当前的实现中,当一个实体从 可观测采集 ,我将它保存在阴影集合中,以便 可观测采集 被发送回服务器后,我可以将删除的项目一起发送,这样实体框架就知道要删除它们。

    沿着这条线的东西:

    protected IDictionary<int, IList> DeletedCollections = new Dictionary<int, IList>();
    
    protected void SubscribeDeletionHandler<TEntity>(ObservableCollection<TEntity> collection)
    {
        var deletedEntities = new List<TEntity>();
        DeletedCollections[collection.GetHashCode()] = deletedEntities;
    
        collection.CollectionChanged += (o, a) =>
            {
                if (a.OldItems != null)
                {
                    deletedEntities.AddRange(a.OldItems.Cast<TEntity>());
                }
            };
    }
    

    现在,如果用户决定将其更改保存到服务器,我可以获取已删除项目的列表,并将其发送给:

    ObservableCollection<Customer> customers = MyServiceProxy.GetCustomers();
    
    customers.RemoveAt(0);
    
    MyServiceProxy.UpdateCustomers(customers);
    

    在这一点上 UpdateCustomers 方法将验证是否删除了任何项,并将它们发送到服务器端。

    这种方法很好地工作,直到您开始考虑这些阴影集合的生命周期。基本上,当 可观测采集 如果是垃圾收集,就无法知道我们需要从字典中删除阴影收集。

    我提出了一些复杂的解决方案,在本例中基本上可以进行手动内存管理。我保持 WeakReference 可观测采集 每隔几秒钟,我会检查引用是否处于非活动状态,在这种情况下,我会删除阴影集合。

    但这似乎是一个可怕的解决方案…我希望StackOverflow的集体天才能够为更好的解决方案提供帮助。

    编辑:

    最后,我决定将 可观测采集 . 服务代理代码是生成的,因此更改它以返回派生类型是一项相对简单的任务。

    谢谢你的帮助!

    3 回复  |  直到 14 年前
        1
  •  1
  •   Binary Worrier    15 年前

    您可以使用 HttpRuntime.Cache (可用于所有项目类型,而不仅仅是Web项目)。

    将每个卷影集合添加到缓存中,可以使用大量的超时时间,也可以使用委托检查原始集合是否仍然存在(或者两者都存在)。

    它不是 可怕地 与您自己的解决方案不同,但它确实使用经过尝试和信任的.NET组件。

    除此之外,您将看到扩展ObservableCollection并使用这个新类(我认为这不是一个小的更改),或者更改/包装 UpdateCustomers 移除阴影集合窗体的方法 DeletedCollections

    对不起,我想不出别的了,但希望这有帮助。
    BW

        2
  •  1
  •   mdma    15 年前

    如果替换ObservableCollection是可能的(例如,如果对所有集合实例使用公共工厂),则可以将ObservableCollection子类化,并添加一个Finalize方法,用于清除属于此集合的已删除项。

    另一种选择是更改计算删除项目的方式。您可以保留原始的收集,并给客户一个简单的副本。当集合返回时,您可以比较这两个集合,以查看哪些项不再存在。如果对集合进行排序,则可以在线性时间内对集合的大小进行比较。如果不进行排序,则修改后的集合值可以放在哈希表中,该哈希表用于查找原始集合中的每个值。如果实体具有自然ID,那么将其用作键是确定返回集合中不存在哪些项(即已删除)的安全方法。这也在线性时间内运行。

    否则,你最初的解决方案听起来也没那么糟糕。在Java中,弱引用可以注册在引用被清除时调用的回调。.NET中没有类似的功能,但是使用轮询是一种近似的方法。我不认为这种方法如此糟糕,如果它有效,那为什么要改变它呢?

    顺便提一句,您不关心getHashCode()为不同的集合返回相同的值吗?使用对集合的弱引用作为键可能更合适,这样就不会发生冲突。

        3
  •  1
  •   stuck    15 年前

    我认为你走的是一条很好的路,在这种情况下我会考虑重构。我的经验是,在99%的情况下,垃圾收集器使内存管理变得很棒——几乎不需要真正的工作。

    但在1%的情况下,需要有人意识到,他们必须提高赌注,并通过在这些领域加强缓存/内存管理而进入“老派”。向你致敬,因为你意识到你正处于这种情况,并试图避免使用IDispose/Weakreference技巧。我想你真的会帮助下一个在你的代码中工作的人。

    至于如何解决问题,我认为你对形势掌握得很好

    -在需要创建对象时要清楚 -当你的物品需要销毁时要清楚。 -当需要将对象推送到服务器上时要清楚

    祝你好运!告诉我们情况:)

    推荐文章