使用带有EF4的MVC 3中的viewModel创建和编辑视图的复杂数据库结构

时间:2012-01-07 16:44:28

标签: c# asp.net-mvc-3 entity-framework-4 razor viewmodel

我很难想出如何解决这个问题。任何帮助都值得赞赏。甚至建议更好的结构符合我的需求:在类别中构建类别项目,并指明它们在类别项目属性列表中的规格。

除其他外,这用于dinamicaly生成用于创建和编辑项目的表单。

长话短说我需要知道我是做得对还是更好(也许是自动化)处理它而不会破坏整个应用。 。

我正在使用Win7 64位计算机中的VWD Express 2010中的MySQL 5,并安装了所有MySQL驱动程序(ODBC和.NET特定提供程序,最后一个与ASP.Net 4不兼容)。其他问题在这里提出,但可以针对一个单独的问题:我正在编写我的所有模型,因为MySql与Linq to SQL不兼容(我可以想象为什么,但不确定)。 。

回到真实主题:

我的模特是:

  • Category - 主要实体,具有名称属性,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来将类别信息及其项目属性集合传递给“创建”和“编辑”视图,并循环浏览ItemProperties以生成字段并在ItemController中工作,接收FormCollection并生成Item及其ItemProperty个对象并将其保存到数据库中。但是这个过程非常糟糕和痛苦:

项目/创建视图:

@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);
}


我的问题在于构建“创建”和“编辑”操作及其各自的视图(请参阅上面我现在是如何执行此操作)。 当我必须使用Category.ItemProperties生成字段并将信息存储在Item对象中并将字段值存储在其ItemProperty对象中时,如何处理这种情况?< /强>


请注意:所有这些代码仅供参考。我的代码类似,但它由特定的控制器和CRUD类别和CategoryItemProperties的特定视图处理,我对此没有任何问题。


抱歉这篇长篇文章。我尽力做到最清楚。如果您需要更多信息,请发表评论。

3 个答案:

答案 0 :(得分:0)

好的rcdmk!首先,我的英语很糟糕,我在这里只是与你分享我的一些经验。

我过去使用MVVM(WPF)+ EF4 + T4构建了这样一个复杂的软件来生成 POCO ,并处理 Microsoft Blend 来处理客户端和视图模型之间的动作,绑定等等!

这很棒!我希望我能帮到你!

PS: 我不知道Blend是否支持ASP.Net但是使用延迟加载创建POCO(Viewmodel)可能对你有所帮助!

答案 1 :(得分:0)

据我所知,Category和相应的CategoryPropertyItems描述了如何创建Item。 Simply Category绘制一个抽象形式,item和item属性是concretes(因为item属性具有Value属性)。因此,在Item / Create Action(GET)中,您可以使用Category和CategoryPropertyItems构建项目及其属性。

公共物品构建(类别类别)         {             Item item = new Item();             item.Category = category;             item.ItemId = ...

        foreach(var categoryItemProperty in category.ItemProperties)
        {
            ItemProperty itemProperty = new ItemProperty();
            itemProperty.Item = item;
            itemProperty.CategoryItemProperty = categoryItemProperty;
            itemProperty.ItemPropertyId = ... 
        }

        return item;
    }

在索引/创建操作的结果中,您可以使用此Item对象,也可以将项目放入ViewModel。

在View中,您可以直接绑定到模型(Item)属性。

此链接可以帮助您。

Editing and binding nested lists with ASP.NET MVC 2 Model Binding To A List

答案 2 :(得分:0)

在缺乏帮助的情况下,我选择使用我已经拥有的解决方案并且它一直在工作,直到我可以转回它(很快,因为我将不得不添加更多功能)并重构我的所有代码,尝试找出一种更好的方法。