在我们的多层业务应用程序中,我们有ObservableCollections
个从服务调用返回的自我跟踪实体。
我们希望能够从集合客户端获取实体,添加,更新和删除实体,然后将这些更改发送到服务器端,并将它们保存到数据库中。
自我跟踪实体,正如其名称所暗示的那样,可以自行跟踪其状态。
当创建新STE时,它具有已添加状态,当您修改属性时,它设置已修改状态,它也可以具有已删除状态,但是当从ObservableCollection
中删除实体时,不会设置此状态(明显)。如果你想要这种行为,你需要自己编写代码。
在我当前的实现中,当一个实体从ObservableCollection
中删除时,我将它保存在一个阴影集合中,这样当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
方法将验证我的阴影收集,并将它们发送到服务器端。
这种方法很好,直到你开始考虑这些影子集合的生命周期。基本上,当ObservableCollection
被垃圾收集时,无法知道我们需要从字典中删除阴影集合。
我提出了一些复杂的解决方案,在这种情况下基本上都是手动内存管理。我向WeakReference
保留了ObservableCollection
,每隔几秒钟检查一次参考是否处于非活动状态,在这种情况下我会删除阴影集合。
但这似乎是一个可怕的解决方案......我希望StackOverflow的集体天才可以为更好的解决方案提供帮助。
编辑:
最后我决定继承ObservableCollection
的子类。生成服务代理代码,因此更改它以返回我的派生类型是一个相对简单的任务。
感谢您的帮助!
答案 0 :(得分:1)
您可以使用HttpRuntime.Cache
(可从所有项目类型中获取,而不仅仅是Web项目),而不是滚动您自己的“弱引用+民意调查是否死亡,是否活着”逻辑。
将每个影子集合添加到缓存中,或者使用大量超时,或者委托可以检查原始集合是否仍然存在(或两者都有)。
与您自己的解决方案不同可怕,但它确实使用了经过尝试和信任的.Net组件。
除此之外,您正在考虑扩展ObservableCollection并使用该新类(我想象这是一个不小的改动),或者更改/包装UpdateCustomers
方法以删除阴影集合形式{{ 1}}
抱歉,我想不出别的什么,但希望这会有所帮助 BW
答案 1 :(得分:1)
如果有可能替换ObservableCollection(例如,如果您对所有集合实例使用公共工厂),则可以继承ObservableCollection并添加Finalize方法,该方法清除属于此集合的已删除项目。
另一种方法是更改计算删除项目的方式。您可以维护原始集合,并为客户端提供浅表副本。当收集回来时,您可以比较两者以查看哪些项目不再存在。如果对集合进行排序,则可以在线性时间内对集合的大小进行比较。如果它们未被排序,则修改后的集合值可以放在哈希表中,并用于查找原始集合中的每个值。如果实体具有自然id,则将其用作密钥是确定返回集合中不存在哪些项目的安全方式,即已删除。这也是线性时间。
否则,您的原始解决方案听起来并不那么糟糕。在java中,WeakReference可以注册在清除引用时调用的回调。 .NET中没有类似的功能,但使用轮询非常接近。我不认为这种方法是如此糟糕,如果它有效,那么为什么要改变呢?
顺便说一下,你不关心GetHashCode()为不同的集合返回相同的值吗?使用对集合的弱引用可能更适合作为键,因此不存在碰撞的可能性。
答案 2 :(得分:1)
我认为你走的是一条好路,我会考虑在这种情况下进行重构。我的经验是,在99%的情况下,垃圾收集器使内存管理变得非常棒 - 几乎不需要真正的工作。
但在1%的情况下,需要有人意识到他们必须通过加强他们在这些领域的缓存/内存管理来提高赌注和“旧学校”。向你致意,因为你意识到自己处于这种状况,并试图避免使用IDispose / WeakReference技巧。我想你真的会帮助下一个在你的代码中工作的人。
至于获得解决方案,我认为你已经很好地掌握了这种情况
- 在需要创建对象时清楚 - 当你的物体需要被摧毁时清楚 - 当你的对象需要被推送到服务器时清楚
祝你好运!告诉我们它是怎么回事:))