C# ASP.NET MVC与viewmodel的多对多关系

C# ASP.NET MVC与viewmodel的多对多关系,c#,asp.net-mvc,entity-framework,viewmodel,navigation-properties,C#,Asp.net Mvc,Entity Framework,Viewmodel,Navigation Properties,我正在尝试显示一个书籍列表,该列表将显示每本书的详细信息。除了与Books模型有多对多关系的属性外,所有这些都可以正常工作。 这是我的图书模型(为了便于阅读,我删除了注释): 如您所见,它将返回一个viewModel,因为我认为这对于如何返回模型数据的组合最有意义。 以下是viewmodel: public class BookListViewModel { public List<Book> Books { get; set; } public int BookI

我正在尝试显示一个书籍列表,该列表将显示每本书的详细信息。除了与Books模型有多对多关系的属性外,所有这些都可以正常工作。
这是我的图书模型(为了便于阅读,我删除了注释):

如您所见,它将返回一个viewModel,因为我认为这对于如何返回模型数据的组合最有意义。
以下是viewmodel:

public class BookListViewModel
{

    public List<Book> Books { get; set; }
    public int BookId { get; set; }
    public string title { get; set; }
    public string author { get; set; }
    public Int32 isbn { get; set; }
    public string series { get; set; }

    public int? GradeLevelId { get; set; }
    public string gradeLevelName { get; set; }

    public int? LexileLevelId { get; set; }
    public string lexileLevelName { get; set; }

    public Recommendation Recommendation { get; set; }
    public int RecommendationTypeId { get; set; }
    public string recName { get; set; }

    public RelevantGenre RelevantGenre { get; set; }
    public int genreId { get; set; }

}
公共类BookListViewModel
{
公共列表书籍{get;set;}
public int BookId{get;set;}
公共字符串标题{get;set;}
公共字符串作者{get;set;}
公共Int32 isbn{get;set;}
公共字符串系列{get;set;}
public int?GradeLevelId{get;set;}
公共字符串gradeLevelName{get;set;}
public int?lexileveloid{get;set;}
公共字符串lexileLevelName{get;set;}
公共建议{get;set;}
公共int建议类型ID{get;set;}
公共字符串recName{get;set;}
公共相关类型相关类型{get;set;}
public int genreId{get;set;}
}
最后,这里是观点:

@model FavBooks.ViewModels.BookListViewModel
@{
ViewBag.Title = "All Books";
Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Books</h2>
<p class="details">
    @Html.ActionLink("Browse All Books in List Format", "FullList", "Books")

</p>

@foreach (var item in Model.Books)
{
    <div class="row fullBorder">
        <div class="col-md-2 col-sm-2">
            <img src="~/Content/Images/harrypotterbook.png" class="bookThumb" alt="Book Image" />
        </div>
        <div class="col-md-3 col-xs-3">
            <h3>
                <a href="@Url.Action("Details", "Books", new { id = item.BookId })" class="darkLink bookTitle">
                    @Html.DisplayFor(modelItem => item.title)
                </a>
            </h3>
            <h4>By @Html.DisplayFor(modelItem => item.author)</h4>
            <p><strong>ISBN:</strong> @Html.DisplayFor(modelItem => item.isbn)</p>
        </div>
        <div class="col-md-3 col-sm-4 bookMargins">
            @{
                if (item.series != null)
                {
                    <p><strong>Series:</strong> @Html.DisplayFor(modelItem => item.series) </p>
                }
                else
                {
                    <p></p>
                }
            }

            <p><strong>Grade Level:</strong> @Html.DisplayFor(modelItem => item.GradeLevel.gradeLevelName )</p>
            <p><strong>Lexile Level:</strong> @Html.DisplayFor(modelItem => item.LexileLevel.lexileLevelName)</p>

        </div>
        <div class="col-md-4 col-sm-3">
            @Html.ActionLink("View Book Details", "Details", "Books", new { id = item.BookId }, new { @class="btn btn-default btnBookDetails" })
        </div>

    </div>   
}
@model FavBooks.ViewModels.BookListViewModel
@{
ViewBag.Title=“所有书籍”;
Layout=“~/Views/Shared/_Layout.cshtml”;
}
书

@ActionLink(“以列表格式浏览所有书籍”、“完整列表”、“书籍”)

@foreach(Model.Books中的var项) { 通过@Html.DisplayFor(modelItem=>item.author) ISBN:@Html.DisplayFor(modelItem=>item.ISBN)

@{ 如果(item.series!=null) { 系列:@Html.DisplayFor(modelItem=>item.Series)

} 其他的 {

} } 等级级别:@Html.DisplayFor(modelItem=>item.GradeLevel.gradeLevelName)

lexilevel:@Html.DisplayFor(modelItem=>item.LexileLevel.lexileLevelName)

@ActionLink(“查看书籍详细信息”、“详细信息”、“书籍”,新建{id=item.BookId},新建{@class=“btn btn default btnBookDetails”}) }
您可以看到“我的视图”使用foreach循环显示Model.Books中的项目列表。对于每本书,我希望它也能显示与本书相关的类型,但它不允许我这样做。GradeLevel和LexileLevel属性连接得很好(它们是一对多),但它似乎没有注册任何不是书本模型直接部分的多对多关系。
我觉得这里缺少了一些基本的东西,或者我的视图模型设置有问题。你知道我在这方面哪里出错了吗?或者我能做些什么来展示每本书的风格

编辑:
让我更具体地介绍一下我的尝试。
我发现可以在另一个foreach中使用foreach来显示循环。但当我尝试这样做时,它告诉我“foreach无法对其进行操作……因为Favbooks.Models.Book不包含GetEnumerator的公共定义”。因此,我尝试将@model更改为IEnumerable,并在整个模型中循环(而不是
foreach(model.Books中的var项)
),但它仍然不起作用。在这种情况下,它给了我一个错误提示:

“BookListViewModel”不包含“RelevantGenes”的定义,并且找不到接受“BookListViewModel”类型的第一个参数的扩展方法“RelevantGenes”(是否缺少using指令或程序集引用?)

因为这不起作用,我将@model与
@model FavBooks.ViewModels.BookListViewModel
保持原样,并尝试输入
@Html.DisplayFor(modelItem=>item.Genres.genreTitle)
,但它无法识别流派或相关流派。
总而言之,问题是,如果我循环使用Model.Books,那么它将无法识别viewmodel中除Books列表之外的任何内容。但是如果我循环使用整个模型,那么它仍然无法识别相关的类型,现在它开始给我另一个类似这样的错误:

传递到字典中的模型项的类型为“FavBooks.ViewModels.BookListViewModel”,但此字典需要类型为“System.Collections.Generic.IEnumerable`1[FavBooks.ViewModels.BookListViewModel]”的模型项


如果这还不完全清楚,我很抱歉。我以前没有对viewmodels进行过太多的操作,我发现我一定是设置错误了,但我只是不知道如何使其工作…

您是否尝试过
.Include()
?这将填充导航属性中的所有相关数据。有关更多详细信息,请参阅

例如:

这将查询BookId=id的书籍记录,并填充所有相关的导航属性

还有
。然后include()

public List Books{get;set;}
的属性应该足够了,因为这将存储与检索到的实体相关的所有数据

下面是如何访问导航属性字段的示例

@model BookListViewModel

foreach(var b in Model.Books)
{
  @HtmlDisplayFor(modelItem=>b.title)

  foreach(var r in b.RelevantGenres)
  {
    @HtmlDisplayFor(modelItem=>r.GenereName)
  }
}

我自己对.netcore mvc还相当陌生,我也不太了解。但如果不能完全解决您的问题,我希望这有助于为您指明正确的方向。

您是否尝试过
.Include()
?这将填充导航属性中的所有相关数据。有关更多详细信息,请参阅

例如:

这将查询BookId=id的书籍记录,并填充所有相关的导航属性

还有
。然后include()

public List Books{get;set;}
的属性应该足够了,因为这将存储所有数据
public class BookListViewModel
{

    public List<Book> Books { get; set; }
    public int BookId { get; set; }
    public string title { get; set; }
    public string author { get; set; }
    public Int32 isbn { get; set; }
    public string series { get; set; }

    public int? GradeLevelId { get; set; }
    public string gradeLevelName { get; set; }

    public int? LexileLevelId { get; set; }
    public string lexileLevelName { get; set; }

    public Recommendation Recommendation { get; set; }
    public int RecommendationTypeId { get; set; }
    public string recName { get; set; }

    public RelevantGenre RelevantGenre { get; set; }
    public int genreId { get; set; }

}
@model FavBooks.ViewModels.BookListViewModel
@{
ViewBag.Title = "All Books";
Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Books</h2>
<p class="details">
    @Html.ActionLink("Browse All Books in List Format", "FullList", "Books")

</p>

@foreach (var item in Model.Books)
{
    <div class="row fullBorder">
        <div class="col-md-2 col-sm-2">
            <img src="~/Content/Images/harrypotterbook.png" class="bookThumb" alt="Book Image" />
        </div>
        <div class="col-md-3 col-xs-3">
            <h3>
                <a href="@Url.Action("Details", "Books", new { id = item.BookId })" class="darkLink bookTitle">
                    @Html.DisplayFor(modelItem => item.title)
                </a>
            </h3>
            <h4>By @Html.DisplayFor(modelItem => item.author)</h4>
            <p><strong>ISBN:</strong> @Html.DisplayFor(modelItem => item.isbn)</p>
        </div>
        <div class="col-md-3 col-sm-4 bookMargins">
            @{
                if (item.series != null)
                {
                    <p><strong>Series:</strong> @Html.DisplayFor(modelItem => item.series) </p>
                }
                else
                {
                    <p></p>
                }
            }

            <p><strong>Grade Level:</strong> @Html.DisplayFor(modelItem => item.GradeLevel.gradeLevelName )</p>
            <p><strong>Lexile Level:</strong> @Html.DisplayFor(modelItem => item.LexileLevel.lexileLevelName)</p>

        </div>
        <div class="col-md-4 col-sm-3">
            @Html.ActionLink("View Book Details", "Details", "Books", new { id = item.BookId }, new { @class="btn btn-default btnBookDetails" })
        </div>

    </div>   
}
var BookList = _context.Book.Where(m=>m.BookId==id).Include(m=>m.Recommendations).Include(m=>m.RelevantGenres)
@model BookListViewModel

foreach(var b in Model.Books)
{
  @HtmlDisplayFor(modelItem=>b.title)

  foreach(var r in b.RelevantGenres)
  {
    @HtmlDisplayFor(modelItem=>r.GenereName)
  }
}