Способы хранить объект через несколько обратных передач

Ради аргумента предполагают, что у меня есть веб-форма, которая позволяет пользователю редактировать подробные сведения о заказе. Пользователь может выполнить следующие функции:

  • Поставка/детали оплаты изменения (весь простой текст / выпадает),
  • Добавляйте/Удаляйте/Редактируйте продукты в порядке - это сделано с сеткой
  • Добавьте/Удалите вложения

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

Платформа объекта (4.0) используется в качестве ORM.

Я хочу позволить пользователям вносить безотносительно изменений, которые они хотят к порядку и только когда они совершают нападки, 'Сохраняют', делают я хочу передать изменения в базе данных. Это не проблема с текстовыми полями/флажками и т.д., поскольку я могу просто полагаться на ViewState для получения запрошенной информации. Однако сетка представляет намного большую проблему для меня, поскольку я не могу выяснить хороший и простой способ сохранить изменения пользователь, сделанный, не передавая изменения в базе данных. Хранение дерева объектов Порядка на Сессии/Состоянии отображения не является действительно опцией, я хотел бы пойти с тем, поскольку объекты могли стать очень большими.

Таким образом, вопрос - как я могу пойти о сохранении изменений пользователь, сделанный до готовым 'Сохранить'.

Быстрое примечание - я искал ТАК, чтобы попытаться найти решение, однако все, что я нашел, были предложения для использования Сессии и/или ViewState - оба из которых я не буду скорее использовать из-за потенциального размера моих деревьев объектов

5
задан Marek Karbarz 7 January 2010 в 21:49
поделиться

13 ответов

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

2
ответ дан 13 December 2019 в 05:36
поделиться

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

Во-вторых, вы можете рассмотреть гибридный подход - используйте состояние сеанса (или кэш) на короткое время, чтобы избежать ненужных переходов к БД или другому внешнему хранилищу. После некоторого количества неактивности запишите состояние кэша на диск или БД. Самый простой способ сделать это, это сериализовать ваши объекты в текст (используя либо сериализацию, либо библиотеку типа proto-buffers). Это поможет вам избежать создания избыточной или дублирующей структуры данных для относительного захвата данных в процессе работы. Если вам не нужно опрашивать содержимое этих данных - это разумный подход.

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

.
2
ответ дан 13 December 2019 в 05:36
поделиться

Не думали ли вы о том, чтобы хранить информацию в JavaScript-объекте, а затем отправлять эту информацию на ваш сервер после того, как пользователь выполнит сохранение?

.
1
ответ дан 13 December 2019 в 05:36
поделиться

Вы должны иметь возможность создать временный файл и сериализовать объект до этого, а затем сохранить только имя временного файла в состояние просмотра. После успешного сохранения записи обратно в базу данных можно будет удалить временный файл.

0
ответ дан 13 December 2019 в 05:36
поделиться

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

Я думаю, что прилипание к базе данных для хранения данных является единственным надежным способом сохранения данных, даже временных. Использование состояния сеанса, контрольного состояния, куки, временных файлов и т.д. может привести к появлению множества вещей, которые могут пойти не так, особенно если ваше приложение находится в веб-ферме.

4
ответ дан 13 December 2019 в 05:36
поделиться

Используйте события домена для захвата действий пользователей, а затем повторите эти действия на снимке модели заказа (фактически, текущее состояние заказа до того, как пользователь начал его изменять).

Храните каждое изменение как серию событий, например UserChangedShippingAddress, UserAlteredLineItem, UserDeletedLineItem, UserAddedLineItem.

Эти события могут быть сохранены после каждого постбэка и требуют только ссылки на соответствующий заказ. Восстановить текущее состояние заказа тогда так же просто, как и переиграть события по хранящимся в данный момент объектам заказа.

При нажатии кнопки "Сохранить" можно воспроизвести события и сохранить обновленную модель заказа в базе данных.

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

Сопровождение невероятно простое, так как благодаря простоте, с которой вы можете реализовать объект домена, автоматизированное тестирование легко используется для того, чтобы убедиться, что система ведет себя так, как вы ожидаете (при этом документируя ваши намерения для других разработчиков).

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

Использование этого подхода не требует внесения изменений в существующую модель домена, поэтому влияние на существующий код минимально. Самый большой минус - это то, что вы понимаете концепцию доменных событий и то, как они используются и злоупотребляются =)

Это фактически тот же самый подход, что и Фредди Риос, с немного более подробным описанием того, как и некоторые хорошие ключевые слова для поиска с =)

http://jasondentler.com/blog/2009/11/simple-domain-events/ и http://www.udidahan.com/2009/06/14/domain-events-salvation/ являются хорошим фоновым чтением о событиях в домене. Вы также можете захотеть прочитать об источнике событий, так как это, по сути, то, что вы будете делать (объект снимка, запись событий, воспроизведение событий, объект снимка еще раз).

1
ответ дан 13 December 2019 в 05:36
поделиться

Если вы искали объекты типа, поместите тип на уровень метода, например:

public T GetValue<T>(string sessionKey)
{

}

Уровень класса больше, если у вас один и тот же объект в сессии, но сеанс может быть расширен до нескольких типов. Я не знаю, что я бы беспокоился о контроле за сессией; Я бы просто позволил ей делать то, что делается на некоторое время, и просто предоставил бы средства для извлечения и сохранения информации более строго типизированным способом (по крайней мере, для потребителя).

Да, индексы не сработали бы; Вы можете создать его как экземпляр и сделать его статическим с помощью:

public class SessionManager
{
    private static SessionManager _instance = null;


    public static SessionManager Create()
    {
       if (_instance != null)
           return _instance;

       //Should use a lock when creating the instance
       //create object for _instance

       return _instance;
    }

    public object this[string key] { get { .. } }
}

И поэтому это статическая заводская реализация, но он также поддерживает единственную точку контакта через статическую ссылку на класс менеджера сеанса внутри. Каждый метод в sessionmanager может обернуть существующий сеанс ASP.NET или использовать собственное внутреннее место хранения.

-121--4321271-

Первая глава превосходного Практического общего Лиспа Петера Зайбеля описывает его причины для любви Лиспа. Итогом является фраза «программируемый язык программирования» - возможность настройки языка в соответствии с вашим доменом или предпочтительным стилем.

-121--763697-

Один сервер: сериализация в файловой системе. Это также позволяет пользователю возобновить работу позже. Несколько серверов: сериализовать его, но сохранить сериализованное значение в базе данных.

Это то, что для этого конкретного пользователя, поэтому, когда вы сохраняете его в БД, вам не очень нужны все реляционные вещи для него.

Если набор данных v. large и количество изменений обычно невелико, вместо этого можно сохранить историю изменений, выполненных пользователем. С помощью этого можно также показать историю изменений + отменить поддержку.

0
ответ дан 13 December 2019 в 05:36
поделиться

как насчет сериализации вашего объекта Домена (содержимое сетки/тележки покупок) в JSON и сохранения его в скрытой переменной ? У Scottgu есть хорошая статья о том, как сериализовать объекты в JSON. Масштабируемый по серверной ферме и, полагаю, не добавит много полезной нагрузки на вашу страницу. Может быть, вы можете написать свой собственный JSON сериализатор, чтобы сделать "компактную сериализацию" (вам не нужно название продукта, ID продукта, SKU ID, и т.д., может быть, вы можете просто "сериализовать" productID и количество)

.
1
ответ дан 13 December 2019 в 05:36
поделиться

2 подхода - создайте комплексное приложение Ajax, которое хранит все на клиенте и только представляет весь пакет изменений на сервере. Я сделал это один раз несколько лет назад с умеренным успехом. Примечание не то, что я хотел бы сохранить, хотя. У вас есть трудное время, синхронизирующее код вашего клиента с помощью сервера и передавающих поля, которые добавляются / удалены / изменились, - это кошмарный.

2-й подход состоит в том, чтобы хранить изменения в базе данных в таблице TEMP или «в ожидании» режиме. Преимущество вашего кода более удобна. Недостатком - это вы должны иметь способ очистить отказаться от изменений из-за тайм-аута сеанса, сбои мощности, других аварий. Я бы взял этот подход к любой новой разработке. Вы можете иметь отдельные таблицы для «ожидающих» и «преданных» изменений, которые открывают совершенно новый уровень функций, которые вы можете добавить. Что, если? Что изменилось? и т.д.

0
ответ дан 13 December 2019 в 05:36
поделиться

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

Затем вы можете хранить сложные бизнес-объекты в апплет, обеспечивать постоянное отслеживание "в процессе" редактирования в течение нескольких сессий через автономное хранилище и легко интегрировать с внутренними службами, которые обеспечивают сохранение / обработку окончательного заказа. Все это при сохранении доступа через Интернет (хотя и закрытие большинства *nix клиентов).

Альтернативы включают Adobe Flex или AJAX, в зависимости от ресурсов и потребностей.

0
ответ дан 13 December 2019 в 05:36
поделиться

Вы учитывались с помощью профиля пользователя? .Net поставляется с SQLProfileProvider прямо из коробки. Это позволит вам позволить каждому пользователю захватить их профиль и сохранить временные данные в виде переменной в профиле. К сожалению, я думаю, что это требует вашего «порядка», чтобы быть сериализуемым, но я считаю, что все варианты, кроме сеанса до сих пор требуют того же.

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

1
ответ дан 13 December 2019 в 05:36
поделиться

Я бы пошел на просмотр, независимо от того, что вы сказали раньше. Если вы храните только необходимые материалы, подобные {ID: XX, NumberofProducts: 3} , и увините каждый элемент, который не выбран пользователем на данный момент; Размер ViewState вряд ли будет проблемой, если вы не храните все объект.

При хранении вложений поместите их во временное храниточное местоположение и ссылайтесь на имя файла в вашей ViewState. Вы можете иметь запланированную задачу, которая очищает папку Temp для каждого файла, которая была в последний раз, сохранена более 1 дня назад или что-то.

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

0
ответ дан 13 December 2019 в 05:36
поделиться

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

Чтобы еще больше уменьшить накладные расходы на сериализацию, я подумал бы об использовании чего-то типа protobuf-net; это может быть использовано в качестве реализации для ISerializable , позволяя очень легковесным сериализованным объектам (обычно намного меньше, чем BinaryFormatter, XmlSerializer и т.д.), которые дешево восстанавливать по запросам страниц.

Когда страница окончательно сохраняется, я обновляю свои доменные сущности из локальной модели и представляю изменения.

Для информации, чтобы использовать объект с протобуф-сетью, атрибутируемый сериализаторами состояния (обычно BinaryFormatter), можно использовать:

// a simple, sessions-state friendly light-weight UI model object
[ProtoContract]
public class MyType {
    [ProtoMember(1)]
    public int Id {get;set;}

    [ProtoMember(2)]
    public string Name {get;set;}

    [ProtoMember(3)]
    public double Value {get;set;}
    // etc

    void ISerializable.GetObjectData(
        SerializationInfo info,StreamingContext context)
    {
        Serializer.Serialize(info, this);
    }

    public MyType() {} // default constructor

    protected MyType(SerializationInfo info, StreamingContext context)
    {
        Serializer.Merge(info, this);
    }
}
0
ответ дан 13 December 2019 в 05:36
поделиться
Другие вопросы по тегам:

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