Вопрос

У меня есть проблемы с привязкой модели в моем приложении ASP.NET MVC 2 RC, которое использует NHIBERNATE для доступа к данным. Мы пытаемся построить приложение в Ruby on Rails Way и имеем очень простую архитектуру, где доменные объекты используются вплоть от базы данных до представления.

Приложение имеет пару доменных объектов, которые могут быть проиллюстрированы следующими двумя классами:

public class Product {
    ...

    public Category Category { get; set; }      
}

public class Category {
    public int Id { get; set; }
    public string Name { get; set; }
}

В представлении о том, что форма редактирования имеет следующий оператор для отображения раскрывающегося списка:

<%= Html.DropDownListFor(model => model.Category.Id, 
       new SelectList(ViewData["categories"] as IList<Category>, "Id", "Name"), 
       "-- Select Category --" ) %>

Пожалуйста, не обращайте внимания на использование данных «непреднамеренного» для просмотра для сохранения сбора категорий.

Метод действия, который получает сообщение формы, аналогичен следующему. Обратите внимание, что атрибут TransactionFilter добавляет обработку транзакций nhibernate и совершает транзакцию, если никаких исключений не происходит, и проверка достигает успеха.

[HttpPost]
[TransactionFilter]
public ActionResult Edit(int id, FormCollection collection) {
    var product = _repository.Load(id);

    // Update the product except the Id
    UpdateModel(product, null, null, new[] {"Id"}, collection);

    if (ModelState.IsValid) {
      return RedirectToAction("Details", new {id});
    }
    return View(product);
}

Моя проблема заключается в том, что product.category.id устанавливается со значением, выбранным в форме, например, Category.id = "2". Использование связующего модели по умолчанию приводит к следующему типу исключения nhibernate:

identifier of an instance of Name.Space.Entities.Category was altered from 4 to 2

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

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

Это было полезно?

Решение 3

Решение, которое мы выбрали в то время, было что -то похожее на это:

TryUpdateModel(product, null, null, new[] {"Category"}, collection);
int categoryId;
if (int.TryParse(collection["Category.Id"], NumberStyles.Integer, CultureInfo.InvariantCulture, out categoryId) && categoryId > 0) {
    product.Category = _categoryRepository.Load(categoryId);
}
else {
    product.Category = null;
}

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

Другие советы

Я решил аналогичную проблему с коробками со спиками на моей странице редактирования, изменив следующую строку

@Html.DropDownListFor(x => x.Employee.Id, new SelectList(ViewBag.Employees, "Id", "DisplayName"))

по

@Html.DropDownListFor(x => x.Employee, new SelectList(ViewBag.Employees, "Id", "DisplayName"))

Поэтому я удалил «.id», как предложил Брайан. Перед изменением модель содержала только удостоверение личности сотрудника, и после изменения переплет также загрузил все детали сотрудника в модель.

Я использовал аналогичные методы с классами LINQ для SQL, прежде чем без проблем. Я не думаю, что вам понадобится пользовательский модельный бинд для этого. UpdateModel должен обновлять класс продукта, который вы передаете в него, - не подключенный к нему категорию подкласс. Проверьте HTML, сгенерированный вспомогательным вспомогательным. Как называется элемент? Это должно быть название поля иностранного ключа в вашей таблице продуктов (например, «Категория» или «Product.categoryid», а не "Category.id"). Если это "category.id" - попробуйте изменить первый параметр DropdownList для либо "model => model.category", либо "model => model.categoryid" (или каким -либо полем иностранного ключа). Это должно привести к тому, что UpdateModel обновляется только поле иностранного ключа в классе продукта, а не идентификатор класса категории.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top