Постоянное обновление и вызов соединений: этот объект в настоящее время доступен только для чтения - PullRequest
0 голосов
/ 17 декабря 2011

Я создаю приложение типа Todo, в котором пользователь может делать заметки и постоянно перемещать заметки по экрану.При каждом изменении позиции «примечания» мне нужно сохранять его в базе данных:

Типичный код для этого:

 private void SaveChanges()
    {
        if (!_context.IsSubmitting)
        {
            this.busyIndicator.IsBusy = true;
            _context.SubmitChanges(subOp =>
            {

                this.busyIndicator.IsBusy = false;
                if (subOp.Error != null)
                {
                    ErrorWindow window = new ErrorWindow(subOp.Error.Message);
                    window.Show();
                }

            }, null);
        }
    }

Однако, как вы можете видеть, я блокирую UIиспользование busyindicator и остановка пользователя для выполнения каких-либо действий во время отправки.Это плохо, особенно для этого приложения.В качестве альтернативы я попытался переместить этот код в другой поток, используя этот код:

    private void SaveChanges()
    {
        ThreadPool.QueueUserWorkItem(waitcall =>
        {
            if (!_context.IsSubmitting)
            {
                //this.busyIndicator.IsBusy = true;
                _context.SubmitChanges(subOp =>
                {
                    Dispatcher.BeginInvoke(() =>
                    {
                        //this.busyIndicator.IsBusy = false;
                        if (subOp.Error != null)
                        {
                            ErrorWindow window = new ErrorWindow(subOp.Error.Message);
                            window.Show();
                        }
                    });

                }, null);
            }

        });
    }

Это работает, и приложение по-прежнему остается отзывчивым.Однако теперь, когда контекст передает изменения, и пользователь работает с той же заметкой, перемещая ее по экрану и т. Д., Привязка пытается изменить свойства объекта, и я получаю исключение:

Этот объект в настоящее времятолько для чтения

Я понимаю, что это очевидно, поскольку контекст представляет изменения.Однако есть ли способ, с помощью которого я могу поддерживать отзывчивость приложения, не показывая индикатор тупой занятости и все еще не получая эти исключения?

Ответы [ 2 ]

1 голос
/ 05 января 2012

Во время SubmitChanges все измененные свойства устанавливаются только для чтения.В вашем случае это свойства позиции.Я предполагаю, что свойства привязаны к позиции заметки.

Возможности:

  1. Не привязывайте к сущности в вашем DomainContext.Привязать к клиенту локальный объект с событиями изменения свойства (возможно, клоном сущности).Используйте свойство Измененные события, чтобы попытаться скопировать изменение в контекстную сущность.Если это не удается (только для чтения), вы можете добавить код, чтобы повторить попытку позже.

  2. Использовать частичную отправку EntityGraph от RIA Services Contrib.riaservicescontrib.codeplex.com Проверьте обсуждения / блоги - предоставляется код для клонирования EntityGraph во временный контекст и отправки временного контекста.Я не думаю, что вы захотите синхронизировать по завершении, потому что это, вероятно, перезапишет новую позицию и заставит окно перескочить.Просто отправь и забудь.Если вы добавляете объект на клиент, и ему нужны автоматически сгенерированные свойства ключа, возвращаемые с сервера (идентификатор и т. Д.).Тогда не используйте временный контекст / частичную отправку для добавления.Заблокируйте пользовательский интерфейс и отправьте добавление в обычном режиме, чтобы ваши клиентские свойства обновлялись по завершении, а частичная отправка не вызывалась до того, как были установлены значения ключей.

Я был бы заинтересован в любом другомвозможные решения.

0 голосов
/ 20 июня 2012

Вы также можете сохранить потокобезопасный счетчик количества ожидающих операций отправки и извлечь следующую из них в обратном вызове текущей операции отправки:

public static int myPendingSubmitOperationsCount;
...
myDataContext.SubmitChanges(mySubmitCallback, null);
...
mySubmitCallback(SubmitOperation so)
{
     //Do important stuff
     if(myPendingSubmitOperationsCount > 0)
     {
         myDataContext.SubmitChanges(mySubmitCallback, null);
         myPendingSubmitOperationsCount -= 1;
     }
}
...