【问题标题】:Scaffolding ModelView creates underlying database tables脚手架 ModelView 创建底层数据库表
【发布时间】:2013-12-29 19:00:34
【问题描述】:

我正在尝试使用 AutoMapper 第一次使用 ViewModel。我有两个模型:

public class Item
{
    public int ItemId { get; set; }
    public bool Active { get; set; }
    public string ItemCode { get; set; }
    public string Name { get; set; }
    public List<ItemOption> ItemOptions { get; set; }
    //...
}

public class ItemOption
{
    public int ItemOptionId { get; set; }
    public string Name { get; set; }
    public string Barcode { get; set; }
    //...
}

我已经变成了两个 ViewModel:

public class ItemDetailViewModel
{
    public int ItemDetailViewModelId { get; set; }
    public int ItemId { get; set; }
    public bool Active { get; set; }
    public string ItemCode { get; set; }
    public string Name { get; set; }
    public List<ItemDetailItemOptionViewModel> ItemOptions { get; set; }
}

public class ItemDetailItemOptionViewModel
{
    public int ItemDetailItemOptionViewModelId { get; set; }
    public int ItemOptionId { get; set; }
    public string Name { get; set; }
    public string Barcode { get; set; }

}

然后我在我的应用程序启动中设置以下内容:

Mapper.CreateMap<Item, ItemDetailViewModel>();
Mapper.CreateMap<ItemOption, ItemDetailItemOptionViewModel>();

最后我搭建了我的 ItemDetailViewModel:

然后我构建了我的项目并通过 /Item/Create 添加了一个新项目

我查看了数据库,希望看到我会在 Item 表中有一个条目,但是我有 ItemDetailViewModel 和 ItemDetailItemOptionViewModel 表,这是我没想到的,数据是 ItemDetailViewModel。

我认为我的脚手架做错了什么?如何在不使其成为主要业务模型的一部分的情况下脱离 ViewModel?

更多详情

如果无法使用 ViewModel 搭建控制器,那么如何在控制器中引用 ViewModel 并将更改保存回数据库?

例如,一旦我从数据库上下文中删除 ItemDetailViewModel,以下内容会发生什么变化?

    //
    // POST: /Item/Create

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(ItemDetailViewModel itemdetailviewmodel)
    {
        if (ModelState.IsValid)
        {
            db.ItemDetailViewModels.Add(itemdetailviewmodel);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(itemdetailviewmodel);
    }

更多详情 [2]

那么我的索引/详细信息应该这样工作是否正确,或者有更好的方法吗?

    //
    // GET: /Item/

    public ActionResult Index()
    {
        var items = db.Items.ToList();
        var itemdetailviewmodel = AutoMapper.Mapper.Map<ItemDetailViewModel>(items);
        return View(itemdetailviewmodel);
    }

    //
    // GET: /Item/Details/5

    public ActionResult Details(int id = 0)
    {
        ItemDetailViewModel itemdetailviewmodel = AutoMapper.Mapper.Map<ItemDetailViewModel>(db.Items.Find(id));
        if (itemdetailviewmodel == null)
        {
            return HttpNotFound();
        }
        return View(itemdetailviewmodel);
    }

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-4 viewmodel


    【解决方案1】:

    脚手架不是那么聪明。标准控制器脚手架模板使用控制器模型创建 DbContext,并假定您使用的是 DB 模型,而不是视图模型,并且它不使用 Automapper。所以你要么不使用脚手架,要么在使用前检查它做了什么。

    你使用脚手架的方式并没有错,只是不应该做你所期望的。

    更新这就是你在没有脚手架的情况下如何做到这一点

    // Without Automapper
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(ItemDetailViewModel model)
    {
        if (ModelState.IsValid)
        {
            var item = new Item() 
            {
                Active = model.Active,
                ItemCode = model.ItemCode,
                Name = model.Name,
                ItemOptions = // code to convert from List<ItemDetailItemOptionViewModel> to List<ItemOption>
            }
            db.Items.Add(item);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
    
        return View(model);
    }
    
    
    // with Automapper - not recommended by author of Automapper
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(ItemDetailViewModel model)
    {
        if (ModelState.IsValid)
        {
            var item = Automapper.Mapper.Map<Item>(model);
    
            db.Items.Add(item);
            db.SaveChanges();
            return RedirectToAction("Index");
        }
    
        return View(model);
    }    
    

    您需要修改 DbContext 以使用 IDbSet&lt;Item&gt; Items 而不是 IDbSet&lt;ItemDetailViewModels&gt; ItemDetailViewModels

    创建 Automapper 是为了从域模型映射到视图模型,而不是相反。我已经这样做了一段时间,但这很麻烦,并且会导致细微的错误和其他维护问题。甚至 Jimmy Bogard 本人says you should not map from view models to domain models

    【讨论】:

    • 所以听起来脚手架不是要走的路!但是,我现在对如何链接数据库和 ViewModel 感到有些困惑 - 我已在我的问题中添加了更多详细信息。
    • 不,似乎脚手架并不总是可行的方法。查看我的更新。
    • 感谢您的帮助 - 还有一个问题,我想我已经知道了。我已将 Index/Details 方法添加到我的问题中 - 我是否以正确的方式解决了这些问题?
    • Index 是完美的。使用Edit,我会将Item 放入一个单独的变量中并检查它是否为null,然后如果它不为null - 映射到视图模型并返回到视图(您的代码可以工作,但只是为了便于阅读)。也可以将using Automapper; 添加到控制器的开头并从两个映射语句中松散Automapper.。否则你就知道了!
    • 执行索引时我得到:异常详细信息:AutoMapper.AutoMapperMappingException:缺少类型映射配置或不支持的映射。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-31
    • 2014-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-27
    • 1970-01-01
    相关资源
    最近更新 更多