我想从两个EF表(Menus和MenuItems)中获取数据。然后我想将结果放入ViewModel。所以我可以轻松地遍历Razor View中的数据。
我已经开始工作了。但我是.Net MVC的新手,所以我想知道我的代码是否可以改进。也许查询可以合并而且更短。我使用AsEnumerable(),我不确定这是否是最佳方法。
我认为我的尝试没问题。但我想听听你的想法。欢迎提出任何代码改进建议。感谢。
控制器类:
public ActionResult Index(int? id)
{
if (id == null) return RedirectToAction("Index", new { controller = "Menu" });
var menu =
(from m in _db.Menus
join mi in _db.MenuItems on m.Id equals mi.MenuId
where m.Id == id
select m).First();
var menuItems =
(from mi in _db.MenuItems.AsEnumerable()
join m in _db.Menus on mi.MenuId equals m.Id
where m.Id == id
select new MenuItem
{
Id = mi.Id,
Name = mi.Name,
Href = mi.Href,
CssClass = mi.CssClass,
CssId = mi.CssId,
Title = mi.Title,
Weight = mi.Weight
});
var model = new MenuModelView
{
Id = menu.Id,
Name = menu.Name,
CssClass = menu.CssClass,
CssId = menu.CssId,
Deleted = menu.Deleted,
MenuItems = menuItems
};
return View(model);
}
ViewModel类:
using System.Collections.Generic;
namespace DesignCrew.Areas.Admin.Models
{
public class MenuModelView
{
public int Id { get; set; }
public string Name { get; set; }
public string CssClass { get; set; }
public string CssId { get; set; }
public bool Deleted { get; set; }
public IEnumerable<MenuItem> MenuItems { get; set; }
}
}
剃刀观点:
@model DesignCrew.Areas.Admin.Models.MenuModelView
@{
ViewBag.Title = "Index";
}
<h2>Menu - @Html.DisplayFor(model => model.Name, new { @class = "control-label col-md-2" })</h2>
<p>
@Html.ActionLink("Create New Item", "Create")
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.MenuItems.First().Id)
</th>
<th>
@Html.DisplayNameFor(model => model.MenuItems.First().Name)
</th>
<th>
@Html.DisplayNameFor(model => model.MenuItems.First().Href)
</th>
<th>
@Html.DisplayNameFor(model => model.MenuItems.First().Title)
</th>
<th>
@Html.DisplayNameFor(model => model.MenuItems.First().CssClass)
</th>
<th>
@Html.DisplayNameFor(model => model.MenuItems.First().CssId)
</th>
<th>
@Html.DisplayNameFor(model => model.MenuItems.First().ParentId)
</th>
<th>
@Html.DisplayNameFor(model => model.MenuItems.First().Weight)
</th>
<th>Options</th>
</tr>
@foreach (var item in Model.MenuItems)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Href)
</td>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.CssClass)
</td>
<td>
@Html.DisplayFor(modelItem => item.CssId)
</td>
<td>
@Html.DisplayFor(modelItem => item.ParentId)
</td>
<td>
@Html.DisplayFor(modelItem => item.Weight)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id = item.Id }, new { @class = "link-menu" }) |
@Html.ActionLink("Delete", "Delete", new { id = item.Id }, new { @class = "link-menu" })
</td>
</tr>
}
</table>
答案 0 :(得分:1)
如果您的EF模型在Menu
和MenuItem
之间具有可导航的外键,则无需明确加入这两个表,并且您可以急切加载子MenuItems
同时您获取父Menu
,只需从父级导航到子级:
var menu = _db.Menus
.Include("MenuItems") // Or, use the typed version on newer EF's
.First(m => m.id == id); // Many LINQ expressions allow predicates
return new MenuModelView
{
Menu = menu.Name,
CssClass = menu.CssClass,
CssId = menu.CssId,
Deleted = menu.Deleted,
MenuItems = menu.MenuItems
}
而且,由于MenuModelView
与Menu
EF实体似乎有很多共性,因此您可以查看使用AutoMapper
。配置完成后,您可以使用以下内容替换手动映射步骤:
return Mapper.Map<Menu, MenuModelView>(menu);
修改强>
这是一个廉价而讨厌的ViewModel
,它包装了您的EF实体,并使用表示层数据对其进行了扩充。纯粹主义者可能会注意到你应该为包裹的EF模型创建新类,尽管如此,你的EF模型似乎模型为Html
:)
public class MenuModelView
{
// Presentation tier stuff
public string PageTitle { get; set; }
public string MetaTagsForSEO { get; set; }
public bool IsThisARegisteredUserSoSkipTheAdverts { get; set; }
// Your EF / Domain Model
public Menu Menu { get; set; }
}
您的剃刀@Model
是MenuModelView
。