У меня были плохие времена, пытаясь понять, как с этим справиться. Любая помощь будет оценена. Даже предложение лучшей структуры, которая соответствует моим потребностям: Создайте элементы категории в категории, указав, как они могут быть в списке свойств элемента категории.
Это используется, помимо прочего, для динамического создания форм для создания и редактирования элементов.
Короче говоря: Мне нужно знать, правильно ли я это делаю или лучше (возможно, автоматизированный) способ справиться с этим, не ломая целое приложение.
.
,
Я работаю с MySQL 5 в VWD Express 2010 на 64-битной машине Win7 со всеми установленными драйверами MySQL (поставщик ODBC и .NET, последний не совместим с ASP.Net 4). Другая проблема возникла здесь, но может быть целью для отдельного вопроса: я пишу все свои модели, потому что MySql не совместим с Linq to SQL (я могу представить почему, но не уверен).
.
,
Возвращаясь к реальной теме:
Мои модели:
Category
- Их основная сущность со свойством name, коллекцией CategoryItemProperty
сущностей и коллекцией Item
сущностей;
CategoryItemProperty
- объект с именем и некоторыми другими свойствами, которые определяют, каким может быть Items
в этой категории (размер поля, маска, ограничение ввода и т. Д.);
Item
- объект, свойства которого основаны на свойствах категории;
ItemProperty
- Свойства элементов (размер поля, маска, ограничение ввода и т. Д.)
Код примерно такой:
public class Category
{
public int CategoryId { get; set }
public string Description { get; set }
//...
public virtual List<CategoryItemProperty> ItemProperties { get; set; }
}
public class CategoryItemProperty
{
public int CategoryItemPropertyId { get; set; }
public string Label { get; set; }
public string Name { get; set; }
public int Size { get; set; }
public int MaxLenght { get; set; }
//...
public virtual Category Category { get; set; }
}
public class Item
{
public int ItemId { get; set; }
public string Description { get; set; }
public int CategoryId { get; set; }
//...
public virtual Category Category { get; set }
public virtual List<ItemProperty> Properties { get; set; }
}
public class ItemProperty
{
public int ItemPropertyId { get; set; }
public int ItemId { get; set; }
public int CategoryItemPropertyId { get; set; }
public string Value { get; set; }
//...
public virtual Item Item { get; set; }
public virtual CategoryItemProperty CategoryItemProperty { get; set; }
}
.
,
Большая проблема здесь, с этим подходом, состоит в том, чтобы сгенерировать форму и обработать данные на стороне контроллера, которые будут сохранены в базе данных.
.
,
Более подробный пример: Создайте простую контактную форму:
Мы создаем Category
с некоторой спецификацией поля:
var category = new Category() { Description = "Simple Contact Form" };
MyEntitySet.Categories.Add(category);
MyEntitySet.SaveChanges();
//...
var name = new CategoryItemProperty() { Label = "Name", Size = 50, MaxLength = 50 };
var message = new CategoryItemProperty() { Label = "Message", Size = 50, MaxLength = 255 };
category.ItemProperties.Add(name);
category.ItemProperties.Add(message);
MyEntitySet.Entry(category).State = EntityState.Modified;
MyEntitySet.SaveChanges();
.
,
До сих пор я придумал создание ViewModel
для передачи информации о категории и ее коллекции свойств элемента в представления Create и Edit и выполнение цикла по ItemProperties
для генерации полей и работы в ItemController
, получение FormCollection
и генерацию Item
и его ItemProperty
s объектов и сохранение их в базе данных. Но этот процесс ужасен и болезненен:
.
Элементы / Создать вид:
@model MyApp.Models.CategoryItemModelView
@Html.EditorFor(m => m.Description);
...
@foreach(var property in Model.ItemProperties)
{
<label>@property.Label</label>
<input type="text" name="@property.Name" size="@item.Size" maxlength="@item.MaxLength" />
}
В контроллере:
// GET: /Items/Create/5
public ActionResult Create(int id)
{
var categoryItemModelView = new CategoryItemModelView();
categoryItemModelView.Populate(id); // this method maps the category POCO to the ViewModel
return View(categoryItemModelView);
}
// POST: /Items/Create/5
[HttpPost]
public ActionResult Create(int id, FormCollection formData)
{
if (ModelState.IsValid)
{
var category = MyEntitySet.Categories.Find(id);
var item = new Item
{
CategoryId = id,
Description = formData["Description"],
// ...
Category = category
};
MyEntitySet.Items.Add(item);
foreach(var property in category.ItemProperties)
{
var itemProperty = new ItemProperty
{
ItemId = item.ItemId,
CategoryItemPropertyId = property.Id,
Value = form[property.Name],
// ...
Item = item,
CategoryItemProperty = property
};
MyEntitySet.ItemProperties.Add(itemProperty);
}
MyEntitySet.SaveChanges();
return RedirectToAction("Index");
}
// Here I don't know how to return the typed data to the user (the form returns empty)
var categoryItemModelView = new CategoryItemModelView(id);
categoryItemModelView.Populate(id); // this method maps the category POCO to the ViewModel
return View(categoryItemModelView);
}
.
,
Моя проблема возникает при создании действий Create и Edit и их соответствующих представлений (см. Выше, как я делаю это прямо сейчас). Как справиться с этим случаем, когда мне нужно использовать Category.ItemProperties
для генерации полей и сохранения информации в объекте Item
, а значения полей в его ItemProperty
объекте?
.
,
Обратите внимание: Весь этот код предназначен только для примера. Мой код похож, но он обрабатывается определенным контроллером и определенными представлениями для CRUD Categories и CategoryItemProperties, и у меня нет проблем с этим.
.
,
Извините за этот длинный текст. Я старался быть максимально ясным. Если вам нужна дополнительная информация, оставьте комментарий, пожалуйста.