我试图显示一系列书籍,这些书籍将显示每本书的详细信息。除了与Books模型具有多对多关系的属性外,它都能正常工作。
这是我的Book模型(我删除了注释以便于阅读):
public class Book
{
public int BookId { get; set; }
public string title { get; set; }
public Int32 isbn { get; set; }
public string author { get; set; }
public string summary { get; set; }
public string series { get; set; }
public string amazonLink { get; set; }
public string pubLink { get; set; }
public int? GradeLevelId { get; set; } //Foreign Key for GradeLevel
public bool needsEdit { get; set; }
public int? LexileLevelId { get; set; } //Foreign Key for LexileLevel
public DateTime dateAdded { get; set; }
public Book()
{
dateAdded = DateTime.Now;
}
public string comments { get; set; }
public virtual GradeLevel GradeLevel { get; set; }
public virtual LexileLevel LexileLevel { get; set; }
//Navigation Properties
public virtual ICollection<Recommendation> Recommendations { get; set; }
public virtual ICollection<RelevantGenre> RelevantGenres { get; set; }
}
两个导航属性(Recommendation和RelevantGenre)用于关联/连接表,以及我遇到问题的地方。为了简单起见,我将重点关注RelevantGenre模型。每本书都可以有多个类型,因此RelevantGenre是Book和Genre之间的连接表。
这是那些模型:
public class RelevantGenre
{
//Both are primary keys
[Key]
[Column(Order = 1)]
public int BookId { get; set; } //Foreign Key to Book
[Key]
[Column(Order = 2)]
public int genreId { get; set; } //Foreign Key to Genre
public virtual Book Book { get; set; } //Nav property
public virtual Genre Genre { get; set; } //Nav property
}
public class Genre
{
public int GenreId { get; set; }
public string genreTitle { get; set; }
public int genreOrder { get; set; }
//Navigation Property to RelevantGenre
public ICollection<RelevantGenre> RelevantGenres { get; set; }
}
这是控制器:
// GET: Books
public ActionResult Index(string filter, string searchString)
{
var viewModel = new BookListViewModel();
if (String.IsNullOrEmpty(searchString) && String.IsNullOrEmpty(filter))
{
var results = from b in db.Books select b;
var resultsList = (results.ToList());
viewModel.Books = resultsList;
return View(viewModel);
}
else
{
var results = from b in db.Books select b;
//Filtering the book list
switch (filter)
{
case "HR":
results = from b in db.Books
join r in db.Recommendations
on new { b.BookId } equals
new { r.BookId }
where (r.RecommendationTypeId == 1)
select b;
break;
default:
results = from b in db.Books select b;
break;
}
if(!String.IsNullOrEmpty(searchString))
{
//Search query results
var searchResults = from b in db.Books
.Where(model => model.title.Contains(searchString) || model.author.Contains(searchString)
|| model.series.Contains(searchString))
select b;
if (searchResults != null )
{
results = searchResults;
}
else
{
ViewBag.SpanText = "Sorry, no results founds. Please try your search again.";
}
}
var resultsList = (results.ToList());
viewModel.Books = resultsList;
return View(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; }
}
最后,这里有观点:
@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>
}
您可以看到我的视图使用foreach循环显示Model.Books中的项目列表。对于每本书,我希望它还能显示与书籍相关的RelevantGenres,但它并没有让我这么做。 GradeLevel和LexileLevel属性连接得很好(那些是一对多),但它似乎没有注册任何不直接属于Book模型的多对多关系。 我觉得我在这里遗漏了一些基本的东西,或者我的视图模型设置存在问题。你看到我在这方面出了什么问题,或者我可以做些什么来展示每本书的类型?
修改
让我对我的尝试更加具体。
我看到here可以在另一个foreach中使用foreach来显示循环。但是,当我尝试这个时,它告诉我&#34; foreach无法操作...因为Favbooks.Models.Book不包含GetEnumerator的公共定义&#34;。所以我尝试将@model更改为IEnumerable&lt;&gt;并循环遍历整个模型(而不是 foreach(var item in Model.Books)
,但它仍然无法正常工作。在这种情况下,它给了我一个错误说:
&#39; BookListViewModel&#39;不包含&#39; RelevantGenres&#39;的定义没有延伸方法&#39; RelevantGenres&#39;接受类型&#39; BookListViewModel&#39;的第一个参数。可以找到(你错过了使用指令或程序集引用吗?)
因为那不起作用,我保留了@model与最初的@model FavBooks.ViewModels.BookListViewModel
,并尝试输入@Html.DisplayFor(modelItem => item.Genres.genreTitle)
,但它不识别Genre或RelevantGenre。
总而言之,问题在于,如果我遍历Model.Books,那么除了图书列表之外,它不会识别视图模型中的任何内容。但是,如果我遍历整个模型,那么它仍然无法识别RelevantGenres,现在它开始给我另一个错误:
传递到字典中的模型项类型为&#39; FavBooks.ViewModels.BookListViewModel&#39;,但此字典需要类型为&#39; System.Collections.Generic.IEnumerable`1 [FavBooks]的模型项.ViewModels.BookListViewModel]&#39;
对不起,如果这还不完全清楚的话。我之前没有和viewmodels一起工作,我发现我一定是设置错了,但我不知道如何让它工作......
答案 0 :(得分:0)
您尝试过.Include()
吗?这将在导航属性中填充所有相关数据。有关更多详细信息,请参考https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/reading-related-data-with-the-entity-framework-in-an-asp-net-mvc-application。
例如:
var BookList = _context.Book.Where(m=>m.BookId==id).Include(m=>m.Recommendations).Include(m=>m.RelevantGenres)
这将查询BookId = id的Book记录,并填充所有相关的导航属性。
还有.ThenInclude()
属性public List<Book> 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还是很陌生,我也不是很了解。但是我希望这可以帮助您指出正确的方向,即使不能完全解决您的问题。