GridView с данными в памяти: где хранить объекты до их сохранения? - PullRequest
0 голосов
/ 08 января 2010

У меня есть GridView с ObjectDataSource . Я хочу позволить пользователю создать несколько объектов, а затем сохранить их за один раз.

Фон: я хочу создать редактор для рецепта. Рецепт имеет базовые свойства (например, имя и происхождение) и содержит ингредиенты (например, 100 г сливочного масла). Я хочу, чтобы пользователь установил все свойства рецепта и позволил ему определить его ингредиенты перед (!!) сохранением его в базе данных. Также должна быть возможность удалить ингредиент из списка. Сохранять рецепт сначала, а затем определять ингредиенты - не вариант.

Мой вопрос: Где хранить ингредиенты до их сохранения в базе данных?

Вот что я обнаружил:

  1. ViewState не является опцией, поскольку метод GetData объекта ObectDataSource является статическим и, следовательно, не может получить доступ к состоянию просмотра.
  2. Сеанс не является опцией, поскольку пользователи должны иметь возможность использовать одну и ту же страницу на разных вкладках одного и того же браузера одновременно.
  3. Контекст не является опцией, потому что он не выдерживает обратного вызова.
  4. Использование LinqDataSource вместо ObectDataSource не работает, поскольку не поддерживает операции удаления, если источник данных не является контекстом данных linq.
  5. Использование уникального идентификатора в QueryString (для определения правильного объекта сеанса) было бы обходным путем, но оно портит URL.

Я какое-то время искал в Интернете и много чего пытался, но безуспешно.

Большое спасибо за любую помощь и любые предложения !!

Ответы [ 2 ]

0 голосов
/ 08 января 2010

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

/// <summary>
/// Set an ID to identify the correct session variable (in case there are several ones).
/// Create this ID when it is needed for the first time.
/// </summary>
private string PageCallID
{
    get
    {
        if (ViewState["PageCallID"] == null) ViewState["PageCallID"] = Guid.NewGuid().ToString("N");
        return ViewState["PageCallID"].ToString();
    }
}

/// <summary>
/// Use a hashtable which is stored into the Session to save the in-memory
/// objects. This helps to keep the viewstate variable at the client small.
/// </summary>
protected Hashtable ServerViewState
{
    get
    {
        string strSessionKey = String.Format("CleverViewState_{0}", PageCallID);
        if (Session[strSessionKey] == null) Session[strSessionKey] = new Hashtable();
        return (Hashtable)Session[strSessionKey];
    }
}

При этом мы можем написать в любой веб-форме:

ServerViewState["MyDataTable"] = myDataTable;

вместо

ViewState["MyDataTable"] = myDataTable;

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

Если кто-нибудь знает лучший способ решить эту проблему, я был бы благодарен за любые отзывы!

0 голосов
/ 08 января 2010

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

Используйте какой-либо пользовательский класс для представления данных для вашей сетки. Вместо использования элемента управления источником данных вручную связывайте объект, используя свойства сетки DataSource и DataMember.

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

При каждой обратной передаче обновляйте объект в кеше и привязывайте его к сетке.

Viewstate - это механизм, который поддерживает идентификацию клиента с помощью временного идентификатора. API кэша asp.net поддерживает состояние данных на сервере.

...