Проблемы с обновлением объекта модели NHibernate содержимым DropDownList

Я новичок в NHibernate, но лучше понимаю EF4.

У меня есть базовая страница «Редактировать элемент», и при отправке я хочу обновить свой объект «Элемент» со значениями из формы. FWIW, я использую FormView и использую новые функции привязки модели WebForms, где это практически возможно.

Мой объект "Item" имеет свойство:

public virtual Category Category { get; set; }

что соответствует отношению FK в базе данных (столбец «CategoryId», указывающий на таблицу «Category».)

Итак, в моей форме есть раскрывающийся список «Категория». Этот раскрывающийся список был загружен со списком всех объектов категории.

При отправке все, что я хочу сделать, это присвоить выбранное значение в раскрывающемся списке «Категория» свойству «Категория» моего объекта «Элемент». Довольно прямолинейно, верно? :)

Однако я столкнулся с трудностью:

  • Я могу легко получить раскрывающийся список.SelectedValue, но я не могу назначить его своему объекту Item. В EF4 мой объект Item будет использовать Foreign Key Association и, следовательно, иметь свойства Category и CategoryId, которые будут автоматически синхронизироваться. Когда я попробовал что-то подобное в NHibernate, я получил Invalid Index for this SqlParameterCollection из-за попытки многократного использования одного столбца.

  • Я легко получаю раскрывающийся список.SelectedItem, но он имеет тип ListItem, который нельзя преобразовать в Category.

  • Я попытался использовать свойство dropdown.DataSource (возможно, доступ к элементу «SelectedIndex-th»), но при выполнении кода это значение DataSource было нулевым.

Мое лучшее (ужасное) решение до сих пор выглядит следующим образом:

var dropdown = (DropDownList)MyFormView.FindControl("dropdown");
var id = dropdown.SelectedValue;
var category = new MyRepository().GetCategoryById(id);
item.Category = category;

Итак, я делаю дополнительный вызов репозитория и снова получаю весь объект категории, когда все, что я действительно хочу сделать, это:

item.CategoryId = id;

Как я должен это делать?


person Merenzo    schedule 08.11.2012    source источник


Ответы (2)


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

var dropdown = (DropDownList)MyFormView.FindControl("dropdown");
var id = dropdown.SelectedValue; // may need to cast to int
item.Category = session.Load<Category>(id);
person Jamie Ide    schedule 08.11.2012
comment
Спасибо Джейми #2: этот подход похож на то, что у меня уже есть, хотя теперь я (частично :) понимаю разницу между Get и Load. В моей ситуации (с Session-per-request) в текущем сеансе во время обратной передачи нет значений категории. Таким образом, он по-прежнему обращается к базе данных, чтобы получить полный объект категории, когда все, что я хочу сделать, это установить CategoryId (который у меня уже есть) для объекта элемента. - person Merenzo; 12.11.2012
comment
Load должен сделать это. Однако я вижу в своем собственном коде, что иногда он все еще попадает в базу данных. Есть две причины, по которым я знаю, когда это произойдет: ленивая загрузка отключена или доступ к свойству, отличному от идентификатора. - person Jamie Ide; 12.11.2012

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

var dropdown = (DropDownList)MyFormView.FindControl("dropdown");
var id = dropdown.SelectedValue;
item.Category = new Category { CategoryId = id };
person UnitStack    schedule 08.11.2012
comment
Спасибо, Джейми №1, хотя у меня это не сработало. Первая ошибка: объект ссылается на несохраненный временный экземпляр. Затем я добавил cascade=All в определение FK в моем HBM. Это дало вторую ошибку: не удалось вставить: [Category#MyID]... NH интерпретирует ваш новый оператор Category {} как запрос на вставку. - person Merenzo; 12.11.2012