【问题标题】:related entities, nested partial views and viewModels相关实体、嵌套的局部视图和视图模型
【发布时间】:2013-11-20 13:40:14
【问题描述】:

我昨天问这个问题的方式不太清楚,没有得到任何好的反馈,所以我再试一次......

我有一个实体,其中包含可以在一个页面上创建、更新和删除的相关实体。

在相关实体由多个成员组成的情况下,假设商店有多个产品,我使用部分视图。

所以网址是 stores.com/store/edit/44

我的编辑操作会抓取 id 为 44 的商店实体,然后找到商店 id 为 44 的产品...

编辑以添加控制器详细信息

public ActionResult Edit(int id = 0)
{
    store store = db.storess.Find(id);
    IList<product> product = db.products.Where(t => t.storeid == store.storeid).ToList();

    var viewModel = new vwstore();
    viewModel.store = store;
    viewModel.products = product;

    return View(viewModel);
}

结束编辑

并将其放入视图模型中...

public store store { get; set; }
public IList<product> products { get; set; }

在我看来,我强烈使用

@model myproject.viewModel.vwstores

我显示商店的详细信息并运行一个 for 循环来像这样显示每个产品。

@for (var p = 0; p < Model.store.products.Count(); c++)
{
    @Html.Partial("_product", Model.product[c]);
}

请注意,我正在将特定产品模型传递给局部视图。

在我的局部视图中,我使用根实体类型进行强类型,而不是像上面那样使用视图模型,因为这是我需要的,也是我传递给局部的...

@model myProjectModel.product

现在我可以显示给定产品的详细信息了。

所以现在这是我的问题。如果产品有自己的相关数据(例如类别)怎么办?


问题

  1. 我填写了 public IList products { get;放; } 通过了解商店 ID。我不知道产品 ID,如何填写类别列表?

  2. 我的期望是在产品部分中嵌套一个类别部分,但传递模型是一个问题。我需要传递带有产品和类别列表的视图模型,但是对于部分产品,只有根实体可用。

  3. 我无法传递这样的视图模型... @Html.Partial("_categories", myviewmodel.categories[c]); 它不会编译。这是 viewdatadictionary 的用途吗?

非常感谢任何和所有帮助。

【问题讨论】:

  • 向我们展示您的控制器,您如何填充视图模型的属性?您是否尝试在 lamda 表达式查询中使用 '.Include("Category") ?您的产品有 CategoryId 属性和 Category 导航属性吗?我们需要查看控制器和您的产品实体来帮助您。
  • 我在上面添加了控制器详细信息。每个类别都有一个带有导航属性的产品 ID。
  • 您的产品应该有一个带有导航属性的类别 ID。这是一篇关于导航属性和 EF msdn.microsoft.com/en-ie/data/jj713564.aspx 的文章
  • 我不明白。类别是产品的子级。一个产品有一个类别的集合。它不能有单个类别 ID。
  • 这取决于你,但你的数据结构是。但如果是我,我会反过来,所以我可以进行查询,比如获取所有类别 id 为 x 的产品。在我看来,类别具有产品集合,而不是相反。如果您想在多个类别中拥有一个产品,则使用带有 Id、ProductId 和 CategoryId 的 ProductCategory 映射表,这将为您提供所需的多对多关系,然后您可以使用连接等并在您的域模型中查询在产品模型中填充类别属性。有很多方法可以回答问题..

标签: c# asp.net-mvc entity-framework model viewmodel


【解决方案1】:

尝试使用调用操作方法的 RenderAction 来呈现视图。使用它你可以填充你的视图模型。

@{ Html.RenderAction("Categories", "Controller", new { productId = product.Id }); }

然后是你的视图模型

public Product product {get;set;}
public IList<Category> Categories {get;set;}

控制器

public ActionResult Categories(int productId)
{
   // populate view model based on  product Id
   return PartialView("_Categories", viewmodel);

}

编辑:

或者只是将类别放在您的产品模型中

public class Product
{
   public int Id {get;set;}
   public string Name {get;set;}
   public virtual ICollection<Category> Categories {get;set;}
}

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

这将允许您循环浏览产品类别:

@foreach (var category in prodocut.Categories)
{
    <td>@category.Name</td>
}

【讨论】:

  • 谢谢。我试试看。
  • 我之前没有使用过路由值——渲染部分中的第三个参数。我应该在这里传递产品 ID 吗?
  • 我明白了。是的你应该。我编辑了我的答案,检查一下。
  • 这似乎是正确的轨道。感谢您的帮助,恭喜您达到 1000!
【解决方案2】:

查看主要问题下方的评论

如果您的模型设置正确并且您正在使用 Include,您可以通过导航属性显示与产品相关的数据,如果您想要产品的类别名称,只需编写 p.Category.Name 即可

public Product
{
   public string Name {get;set;};
   [ForiegnKey("Category")]
   public CategoryId {get;set;};

   public Category Category {get; set;}
} 

拉姆达;

db.Products.Where(x => x.ShopId == shopId).Include("Category").ToList();

或者您正在访问数据。

然后您可以使用

访问类别数据
p.Category.Name

【讨论】:

  • 类别需要是一个列表。此外,我需要遍历类别列表并为与给定产品相关的每个类别呈现一个部分。那有意义吗?我可能在最初的问题中并不清楚这一点。
  • 我不得不渲染一个部分,因为我希望能够在同一页面上创建/编辑每个类别以及其他所有内容,因此我必须为每个类别传递模型。跨度>
  • 我不知道你为什么要渲染所有这些部分。您需要重新考虑您的视图模型。您不需要为每个模型传递模型。只是身份证。您可以将 Id 传回给方法以获取您想要使用的记录,因此一旦 categoryId 在视图中,您可以将其存储在某处并将其传回,如果它是您排序的产品模型的一部分。这里不要太拘泥于惯例,你不必传递所有这些模型,这就是观点模型。
猜你喜欢
  • 1970-01-01
  • 2017-04-10
  • 1970-01-01
  • 2019-02-13
  • 1970-01-01
  • 1970-01-01
  • 2013-08-29
  • 2011-05-20
  • 1970-01-01
相关资源
最近更新 更多