我正在使用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;
}
CONTROLLER
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 />
提前致谢
答案 0 :(得分:1)
我会说问题出在代码的这一部分:
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是一个“唯一”KEY(就像你在代码中所示),你会发现帖子本身。
比你创建“模型”。并为每个帖子做这个。最后,“模型”将仅包含第一个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的元组,另一个是与该帖子关联的图像列表。
答案 1 :(得分:0)
下面,我将为您提供2种使代码正常工作的方法。
第一个是&#34;正确&#34;实现您正在尝试做的事情的方法,第二个是修复您正在使用的当前代码。
获取饮料,并阅读良好。 注意:这一切都在我的头脑中(所以请提前原谅 - 只需评论需要纠正的任何内容)
您似乎正在使用Entity Framework。 (如果没有,那么为什么不?)
那就是说,我会调查Entity Framework Relationships & Navigation Properties。
这正是数据库关系的用途。您的代码目前正在大量使用内置功能,并且您不必要地使用Tuple
。 EF允许您使用已经创建的真实对象。
这里是一个简短的(ish)方式,你应该更新你的结构(这个例子是使用EF Code-First - 我发现从我在程序中使用的已经创建的类中创建数据库更容易):
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; }
}
这为您提供了一对多关系&#34;一个帖子&#34;有很多图像文件&#34;。 virtual
类中Images
的{{1}}属性表示它是&#34;导航属性&#34; - 这意味着EF可以找出与该帖子匹配Post
的{{1}}之间的关系。这取决于FluentAPI的惯例(TL; DR)
了解更多信息,了解Code First Relationships在实体框架中的工作方式。
然后,您的控制器可以从您的上下文中返回ImageFile
。
PostID
注意:您需要在文件的顶部包含List<Post>
使用语句,以便将public ActionResult Posts()
{
var posts = _yourDbContext.Posts.Include(x => x.Images).ToList();
return View(posts);
}
方法与lambda表达式一起使用
进一步说明:如果你没有&#34;压扁&#34;结果为using System.Data.Entity
,那么可能不(在我的头顶)需要使用Include()
方法 - TL; DR:在呈现页面时,它仍然具有范围内的上下文,并且能够使用它仍然使用的查询(List<>
)来访问导航属性(延迟加载)。 Include()
只需使用预先加载即可将图片拉出并将其放入IQueryable<>
。
然后,在您的视图中,您可以简单地使用Include()
作为List<>
,迭代您传入的List / IEnumerable;以这种方式引用@model
属性。
像这样:
IEnumerable<Post>
使用这种方式将使您(使用更少的代码),并使用您的类通常在OOP中设计它们。
我还包括了一个&#34;脏&#34;回答 - 使用您正在使用的当前方法,在下面:
与@ Jauch的答案类似,但对代码和您的观点更加浓缩:
您的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
}
。
您只需返回一个博客帖子列表,如下所示:
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>>>
- 让我们说Tuple
。
然后在Model
内,您可以引用item
(作为item
)和Value1
(作为Post
的图像)
像这样:
Value2
我希望无论您采用哪种方法,这都可以帮助您完成项目。
我会建议研究EF的关系功能并使用导航属性,以使您的代码更清晰(并且您的生活更轻松)。
希望这有帮助! :)