我的博客只检索一篇文章

本文关键字:一篇 文章 检索 我的 | 更新日期: 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; }
}

这给了你一个一对多的关系,"一个帖子"有"多个图像文件"。ImagesPost类中的virtual属性意味着它是一个"导航属性"——这意味着EF可以计算出具有匹配PostIDImageFile与该职位之间的关系。这取决于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<>中。

<<h2>视图/h2>

然后,在你的视图中,你可以简单地使用@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,另一个是与该文章相关的图像列表。