我的博客只检索一篇文章
本文关键字:一篇 文章 检索 我的 | 更新日期: 2023-09-27 18:03:30
我正在c# MVC中创建一个博客,但是我在博客帖子上遇到了问题。从帖子列表中,只检索到一个帖子,并且是最后一个帖子。我想检索所有博客文章及其相关图片…
博客模型 public class Blog
{
[Key]
public int BlogID { get; set; }
public string Title { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
public class Post
{
[Key]
public int PostID { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogID { get; set; }
public bool hasImages { get; set; }
public virtual Blog Blog { get; set; }
public virtual ICollection<ImageFile> ImageFiles { get; set; }
}
public class ImageFile
{
[Key]
public int ImageID { get; set; }
public string ImageName { get; set; }
public string ImageType { get; set; }
public byte[] ImageBytes { get; set; }
public int PostID { get; set; }
public virtual Post Post { get; set; }
}
检索文章+图片的方法
public Tuple<IEnumerable<Post>, IEnumerable<ImageFile>> getAllBlogData()
{
var AllPosts = _entities.Posts.ToList();
Tuple<IEnumerable<Post>, IEnumerable<ImageFile>> model = null;
foreach (var post in AllPosts)
{
var posts = AllPosts.Where(e => e.PostID == post.PostID);
if (posts != null)
{
//checks if a blog post has images
if (post.hasImages)
{
var images = _entities.ImageFiles.Where(e => e.PostID == post.PostID);
model = new Tuple<IEnumerable<Post>, IEnumerable<ImageFile>>(posts, images);
}
else
{
model = new Tuple<IEnumerable<Post>, IEnumerable<ImageFile>>(posts, null);
}
}
}
return model;
}
控制器public ActionResult Posts()
{
return View(_blogrepository.getAllBlogData());
}
视图@model Tuple<IEnumerable<Winter.Domain.Entities.Post>, IEnumerable<Winter.Domain.Entities.ImageFile>>
@{
ViewBag.Title = "Posts";
}
<hgroup>
<h3>BLOG</h3>
</hgroup>
@foreach (var post in Model.Item1)
{
<p class="container images">
@if (Model.Item2 != null)
{
foreach (var image in Model.Item2)
{
<span>
<img src="data:image/png;base64,@Convert.ToBase64String(image.ImageBytes)" />
</span>
}
<div class="clearfix"></div>
}
<hgroup>
<h2>@Html.DisplayFor(modelItem => post.Title)</h2>
</hgroup>
<span>
@Html.DisplayFor(modelItem => post.Content)
</span>
</p>
}
<hr />
提前感谢
下面,我给你两种使你的代码工作的方法。
第一个是"正确"的方式来实现你正在尝试做的事情,第二个是你正在使用的当前代码的修复。
喝杯饮料,好好读一本书。注意:这些都是我的想法(所以请提前原谅-只需评论任何需要纠正的地方)1)"正确"的做法:
看起来你正在使用实体框架。(如果没有,那么为什么不呢?)
也就是说,我会研究实体框架关系&导航属性。
这正是数据库关系的作用。您的代码目前正在对一个内置特性进行繁重的工作,并且您不必要地使用了Tuple
。EF允许你使用你已经创建的真实的对象。
这里有一个简短的(ish)方法,你应该更新你的结构(这个例子是使用EF Code-First -我发现它更容易从我在程序周围使用的已经制作的类创建DB):
public class Post
{
public int Id { get;set; }
public string Title { get; set; }
// Other properties etc.
public virtual ICollection<ImageFile> Images { get; set; }
}
public class ImageFile
{
public int Id { get; set; }
public byte[] ImageBytes { get; set; }
[ForeignKey(nameof(Post))]
public int PostId { get; set; }
[ForeignKey(nameof(PostId))]
public Post Post { get; set; }
}
public class Post
{
public int Id { get;set; }
public string Title { get; set; }
// Other properties etc.
public virtual ICollection<ImageFile> Images { get; set; }
}
public class ImageFile
{
public int Id { get; set; }
public byte[] ImageBytes { get; set; }
[ForeignKey(nameof(Post))]
public int PostId { get; set; }
[ForeignKey(nameof(PostId))]
public Post Post { get; set; }
}
这给了你一个一对多的关系,"一个帖子"有"多个图像文件"。Images
在Post
类中的virtual
属性意味着它是一个"导航属性"——这意味着EF可以计算出具有匹配PostID
的ImageFile
与该职位之间的关系。这取决于FluentAPI的约定(TL;DR)
查看代码优先关系如何在实体框架中工作以获取更多信息。
h2控制器你的控制器可以从你的上下文中返回一个List<Post>
。
public ActionResult Posts()
{
var posts = _yourDbContext.Posts.Include(x => x.Images).ToList();
return View(posts);
}
注意:您需要在文件的using语句的顶部包含using System.Data.Entity
,以便将Include()
方法与lambda表达式一起使用。
进一步注意:如果你没有将结果"平坦化"到List<>
,那么你可能不(我的头的顶部)需要使用Include()
方法- TL;DR:当页面被渲染时,它仍然具有范围内的上下文,并且能够使用查询(IQueryable<>
)访问导航属性它仍然使用(延迟加载)。Include()
只是使用急切加载将图像拉出并放置在List<>
中。
然后,在你的视图中,你可以简单地使用@model
作为IEnumerable<Post>
,迭代你传入的List/IEnumerable;以这种方式引用Images
属性
一样:
@model IEnumerable<Your.Namespace.Post>
// Other fluff - page title etc.
@foreach (var post in Model)
{
foreach (var image in post.Images)
{
// Display each image - @image.ImageBytes
}
<h1>@post.Title</h1>
// Other @post.Property printing, here
}
使用这种方式将使您能够(使用更少的代码),并将您的类用于通常在OOP中设计的目的。
我还包括了一个"肮脏"的答案-使用您正在使用的当前方法,如下:
2)代码的"脏"修复:
类似于@Jauch的回答,但是对于代码和视图来说更简洁:
你的getAllBlogPosts()
方法只是返回迭代中的最后一篇文章,每次-你每次都覆盖model
。
您可以简单地返回一个博客文章列表,像这样:
private List<Tuple<Post, IEnumerable<ImageFile>>> GetAllBlogPosts()
{
var allPosts =
_entities.Posts.Select(
post =>
new Tuple<Post, IEnumerable<ImageFile>>(
post,
_entities.ImageFiles.Where(x => x.PostID == post.PostID)));
return allPosts.ToList();
}
然后,在您的视图中,您可以简单地迭代.Item2
属性(图像),而不必事先进行null
检查。
这是因为,即使没有结果,IEnumerable<ImageFile>
的结果也只是一个空集合。
在视图中,您的模型将是IEnumerable<Tuple<Post, IEnumerable<ImageFile>>>
(其中FQNS
是您的类的完全限定名称空间):
@model IEnumerable<Tuple<FQNS.Post, IEnumerable<FQNS.ImageFile>>>
你的视图然后可以遍历Model
中的每个Tuple
-让我们说item
。
然后在item
中,您可以引用Value1
(即Post
)和Value2
(即Post
的图像)。
一样:
@foreach (var item in Model)
{
<p class="container images">
foreach (var image in item.Item2)
{
<span>
<img src="data:image/png;base64,@Convert.ToBase64String(image.ImageBytes)" />
</span>
}
<div class="clearfix"></div>
<hgroup>
<h2>@Html.DisplayFor(x => item.Value1.Title)</h2>
</hgroup>
<span>
@Html.DisplayFor(x => item.Value1.Content)
</span>
</p>
}
无论你采用哪种方法,我希望这对你的项目有所帮助。
我强烈建议研究EF的关系功能和使用导航属性,以使你的代码更干净(和你的生活更容易)。
希望这对你有帮助!:)
我想说问题在这部分代码:
public Tuple<IEnumerable<Post>, IEnumerable<ImageFile>> getAllBlogData()
{
var AllPosts = _entities.Posts.ToList();
Tuple<IEnumerable<Post>, IEnumerable<ImageFile>> model = null;
foreach (var post in AllPosts)
{
var posts = AllPosts.Where(e => e.PostID == post.PostID);
if (posts != null)
{
//checks if a blog post has images
if (post.hasImages)
{
var images = _entities.ImageFiles.Where(e => e.PostID == post.PostID);
model = new Tuple<IEnumerable<Post>, IEnumerable<ImageFile>>(posts, images);
}
else
{
model = new Tuple<IEnumerable<Post>, IEnumerable<ImageFile>>(posts, null);
}
}
}
return model;
}
首先,加载所有的帖子:
var AllPosts = _entities.Posts.ToList();
然后迭代AllPosts上的每个帖子,并查找与此具有相同ID的所有帖子:
foreach (var post in AllPosts)
{
var posts = AllPosts.Where(e => e.PostID == post.PostID);
假设PostID是一个"唯一"键(如代码中所示),您将只找到帖子本身。
然后创建"模型"。对每个帖子都这样做。最后,"model"将只包含来自第一个foreach的最后一篇文章。
我认为你需要返回一个"列表"的帖子(和相关的图像),所以,我会尝试以这种方式改变代码:
public List<Tuple<Post, IEnumerable<ImageFile>>> getAllBlogData()
{
var list = new List<Tuple<Post, IEnumerable<ImageFile>>();
Tuple<Post, IEnumerable<ImageFile>> tuple = null;
var AllPosts = _entities.Posts.ToList();
foreach (var post in AllPosts)
{
//checks if a blog post has images
if (post.hasImages)
{
var images = _entities.ImageFiles.Where(e => e.PostID == post.PostID);
tuple = new Tuple<Post, IEnumerable<ImageFile>>(post, images);
}
else
{
tuple = new Tuple<Post, IEnumerable<ImageFile>>(post, null);
}
list.Add(tuple);
}
return list;
}
当然,调整你的文件来处理列表,而不是"模型"。
上面的代码应该通过一个包含元组的列表返回博客中的所有文章,其中一个数据是POST,另一个是与该文章相关的图像列表。