Как отразить изменения, внесенные в модель на сервере приложений, в модель? - PullRequest
0 голосов
/ 18 ноября 2011

каждый.

Преамбула. Давайте посмотрим на эту типичную ситуацию. Вот 3-х уровневое приложение:

  • Клиент WPF (или Silverlight, это не имеет значения), построенный на MVVM;
  • Служба WCF (сервер приложений);
  • некоторые СУБД в качестве хранилища.

Вот простая модель домена "элементы порядка заказа":

[DataContract(IsReference = true)]
public class Order : INotifyPropertyChanged
{
    [DataMember]
    public Int32 Id { ... }
    [DataMember]
    public Decimal Total { ... }
    [DataMember]
    public Decimal Discount { ... }
    [DataMember]
    public ObservableCollection<OrderItem> Items { ... }
}

[DataContract(IsReference = true)]
public class OrderItem : INotifyPropertyChanged
{
    [DataMember]
    public Int32 Id { ... }
    [DataMember]
    public String Name { ... }
    [DataMember]
    public Decimal Price { ... }
    [DataMember]
    public Decimal Quantity { ... }
    [DataMember]
    public Order Order { ... }
    [DataMember]
    public Int32 OrderId { ... }
}

Свойства Order.Id и OrderItem.Id - это свойства идентичности. Свойства Order.Total и Order.Discount рассчитываются свойствами. Идентификационные и вычисляемые свойства не могут быть установлены на стороне клиента - они должны быть установлены на сервере, их значения зависят от логики сервера. Кроме того, сервер приложений может добавлять в заказ новые товары (например, подарки) или изменять количество существующих товаров (в зависимости от состояния товара).

На стороне клиента эти модели заключены в модели соответствующих представлений:

public class OrderVM : INotifyPropertyChanged
{
    private Order model;

    public OrderVM(Order model)
    {
        this.model = model;

        ...
    }

    public Int32 Id { ... }
    public Decimal Total { ... }
    public Decimal Discount { ... }
    public ObservableCollection<OrderItemVM> Items { ... }

    // ...
}

public class OrderItemVM : INotifyPropertyChanged
{
    public OrderItemVM(OrderItem model)
    {
        ...
    }

    public Int32 Id { ... }
    public String Name { ... }
    public Decimal Price { ... }
    public Decimal Quantity { ... }

    // ...
}

Классы модели реализуют INPC, поэтому, если модель была изменена вне пользовательского интерфейса, модель представления отразит эти изменения.

Сервер приложений - это служба WCF. Вот это контракт:

[ServiceContract(...)]
public interface OrderService
{
    [OperationContract(...)]
    Order SaveOrder(Order order);
}

Что делает OrderService.SaveOrder: он получает заказ, получает идентификационные данные и рассчитанные свойства, изменяет заказ (добавляет или изменяет элементы) и возвращает тот же заказ обратно клиенту.

OrderVM имеет команду «Применить». Представление, отображающее OrderVM, имеет кнопку, которая привязана к OrderVM.Apply. OrderVM.Apply должен вызвать OrderService.SaveOrder:

void ApplyExecute()
{
    var savedOrder = ordersService.SaveOrder(model);
}

Вопрос. С точки зрения CLR, исходный порядок (поле OrderVM.order) и saveOrder - это разные объекты. Мне нужно отразить изменения, которые теперь присутствуют в saveOrder, поэтому они должны отображаться пользователю.

Есть ли общие подходы или лучшие практики, как это сделать? Пожалуйста, примите во внимание, что:

  • команда «Применить», а не «Сохранить и закрыть»: пользователь должен оставаться в том же виде в том же порядке;
  • это простая модель, реальные модели будут более сложными.

Спасибо.

1 Ответ

0 голосов
/ 18 ноября 2011

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

При вызове этого пакета вы получаете новые значения ииметь возможность обновлять модель и ViewModel соответственно.

Конечно, просто запросить базу данных для всех данных проще, но это может стоить слишком большой полосы пропускания и / или времени обработки.

...