Re[2]: Покритикуйте архитектуру обмена данными для smart кли
От: Alexander Polyakov  
Дата: 17.06.08 17:39
Оценка:
Здравствуйте, samius, Вы писали:

>Здесь меня немного пугает обилие кода, связанным с поддержкой сообщений об изменении DTO объектов и довольно плотной подпиской на все сообщения ClientContext-ом.

Есть предположение, что можно написать вот такой базовый класс для DTO

    public class DataTransferObjectBase<TLinqToSqlObject>
    {
        protected T GetValue<T>(Expression<Func<TLinqToSqlObject, T>> expression)
        {
            //TODO: implement this
            throw new NotImplementedException();
        }

        protected void SetValue<T>(Expression<Func<TLinqToSqlObject, T>> expression, T value)
        {
            //TODO: implement this
            throw new NotImplementedException();
        }

        protected IEnumerable<T> GetValue<T>(
            Expression<Func<TLinqToSqlObject, EntitySet<T>>> expression) where T : class
        {
            //TODO: implement this
            throw new NotImplementedException();
        }
    }

пример конкретного DTO
    public class OrderDTO : DataTransferObjectBase<Order>
    {
        public DateTime? OrderDate
        {
            get
            {
                return GetValue(x => x.OrderDate);
            }
            set
            {
                SetValue(x => x.OrderDate, value);     
            }
        }

        public Customer Customer
        {
            get
            {
                return GetValue(x => x.Customer);
            }
            set
            {
                SetValue(x => x.Customer, value);
            }
        }

        public IEnumerable<OrderDetail> OrderDetails
        {
            get
            {
                return GetValue(x => x.OrderDetails);
            }
        }
    }

Сообщения об изменениях, на которые подписывается ClientContext, будут реализованы в базовом классе DataTransferObjectBase. Помимо этого в базовом классе реализуется логика управления связями между DTO объектами, например, OrderDTO.Customer, OrderDTO.OrderDetails.

Второй вариант -- сделать DTO автогенеренными.


>Накопление истории изменений и применение ее на сервере тоже может оказаться громоздким.

Если говорить схематично, история изменений будет накапливаться в виде простой структуры ("Тип LINQtoSQL объекта", "Значение Primary Key-я", "Имя свойства", "Значение свойства"). Возможно, потребуется передача значений всех свойств. Кроме того, будут аналогичные схемы для insert и delete. Еще timpstamp-ы. Но все это будет выполнятся в инфраструктурных классах, и вроде не так уж это сложно получается.

>Если нет — могу предложить вариант, где ClaimDTO и граф объектов являются надстройкой над типизированным DataSet-ом.

Мы рассматривали возможность использования DataSet-ов в качестве DTO. DataSet все-таки отличается от графа связанных объектов. В случае графа -- если объекты графа теряют ссылку на какой-либо объект, то он уже не пренадлежит этому графу, и его уберет сборщик мусора. В случае DataSet-а такого нет -- DataSet жестко хранит все DataRow в себе. Пример, в котором это проявляется, это сценарий с Lookup-ом. Lookup -- это поле на форме, значение поля можно выбирать из списка, список может быть большим, возможно, с пейджингом (например, список продуктов). Если пользователь меняет значение Lookup-а, то в случае графа объекта мы просто выставляем новое значение
orderItem.Product = newProduct

Новый продукт присоединился к графу, старый ушел к сборщику мусора. newProduct берется из списка, который показывается пользователю, либо по Id подгружается с сервера.
В случае с DataSet-ом, у нас проблемы. Мерджить DataSet-ы? или не иметь свойство Product у orderItem, и работать с двумя датасетами и выдергивать Product из второго DataSet-а по Id?
ClientContext (лучше его назвать просто ChangesTracker) не накладывает такой жесткой связи на множество объектов как DataSet. Между DataSet-ом и DataRow двухстороння связь -- DataSet знает о DataRow, и DataRow знает о DataSet. В случает ClientContext-а -- DtoObject хранит ссылку на ClientContext (точнее на делегат из ClientContext), а ClientContext не хранит ссылку на DtoObject.

>При использовании LINQ to SQL, такой DataSet вообще не обязан повторять схему БД, может содержать любую избыточную информацию и служить буфером для изменений в ClaimDTO или в схеме БД.

Схему типизированного DataSet-а каждый раз рисовать вручную?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.