Как отслеживать объекты, удаленные из ObservableCollection в сценариях CRUD?

В нашем многоуровневом бизнес-приложении мы имеем 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 собран "мусор" нет никакого способа знать, что мы должны удалить теневой набор из нашего словаря.

Я предложил некоторое сложное решение, которое в основном делает ручное управление памятью в этом случае. Я сохраняю a WeakReference к ObservableCollection и каждые несколько секунд, которые я проверяю, чтобы видеть, неактивна ли ссылка, в этом случае я удаляю теневой набор.

Но это походит на ужасное решение... Я надеюсь, что коллективный гений StackOverflow может пролить свет на лучшее решение.

Править:

В конце я решил пойти с разделением на подклассы ObservableCollection. Сервисный код прокси сгенерирован так, это была относительно простая задача изменить его для возврата моего производного типа.

Спасибо за всю справку!

5
задан Yannick Motton 12 December 2011 в 15:45
поделиться

3 ответа

Вместо того, чтобы использовать собственную логику «слабая ссылка + опрос Is it Dead, Is it Alive», вы можете использовать HttpRuntime.Cache (доступно для всех типов проектов, не только веб-проекты).

Добавьте каждую теневую коллекцию в кэш либо с большим таймаутом, либо с помощью делегата, который может проверить, жива ли исходная коллекция (или и то, и другое).

Оно не ужасно отличается от вашего собственного решения, но оно использует проверенные и проверенные компоненты .Net.

Помимо этого, вы планируете расширить ObservableCollection и вместо этого использовать этот новый класс (что, как я полагаю, немалое изменение) или изменить / обернуть метод UpdateCustomers для удаления формы теневой коллекции DeletedCollections

Извините, я больше ничего не могу придумать, но надеюсь, что это поможет.
BW

1
ответ дан 15 December 2019 в 06:17
поделиться

Если замена ObservableCollection возможна (например, если вы используете общую фабрику для всех экземпляров коллекций), вы можете создать подкласс ObservableCollection и добавить метод Finalize, который очищает удаленные элементы, принадлежащие этой коллекции.

Другой альтернативой является изменение способа вычисления удаляемых элементов. Вы можете сохранить исходную коллекцию и дать клиенту неглубокую копию. Когда коллекция вернется, вы можете сравнить две, чтобы увидеть, каких предметов больше нет. Если коллекции отсортированы, то сравнение может быть выполнено за линейное время по размеру коллекции. Если они не отсортированы, то измененные значения коллекции могут быть помещены в хэш-таблицу, которая используется для поиска каждого значения в исходной коллекции. Если у сущностей есть естественный идентификатор, то использование его в качестве ключа является безопасным способом определения того, какие элементы отсутствуют в возвращаемой коллекции, то есть были удалены. Это также работает в линейном времени.

В остальном ваше оригинальное решение звучит не так уж плохо. В java WeakReference может зарегистрировать обратный вызов, который вызывается, когда ссылка очищается. В .NET нет аналогичной функции, но использование опроса является близким приближением. Я не думаю, что этот подход настолько плох, и если он работает, зачем его менять?

Кстати, разве вас не беспокоит, что GetHashCode () возвращает одно и то же значение для разных коллекций? Использование слабой ссылки на коллекцию может быть более подходящим в качестве ключа, тогда нет шансов на коллизию.

1
ответ дан 15 December 2019 в 06:17
поделиться

Думаю, вы на правильном пути, я бы подумал о рефакторинге в этой ситуации. Мой опыт показывает, что в 99% случаев сборщик мусора делает управление памятью отличным - почти никакой реальной работы не требуется.

, но в 1% случаев требуется, чтобы кто-то осознал, что им нужно повысить ставку и перейти на «старую школу», усилив управление кэшированием / памятью в этих областях. снимаю шляпу перед вами за осознание того, что вы находитесь в такой ситуации, и за попытки избежать уловок IDispose / WeakReference. Я думаю, вы действительно поможете следующему парню, который будет работать над вашим кодом.

Что касается решения проблемы, я думаю, вы хорошо разбираетесь в ситуации.

- будьте ясны, когда ваши объекты должны быть созданы -Будьте ясны, когда ваши объекты должны быть уничтожены -будьте ясны, когда ваши объекты нужно отправить на сервер

удачи! расскажите, как это происходит :)

1
ответ дан 15 December 2019 в 06:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: