我的博客只检索了一篇帖子

时间:2016-08-23 10:50:13

标签: c# asp.net-mvc

我正在使用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 />

提前致谢

2 个答案:

答案 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;实现您正在尝试做的事情的方法,第二个是修复您正在使用的当前代码。

获取饮料,并阅读良好。 注意:这一切都在我的头脑中(所以请提前原谅 - 只需评论需要纠正的任何内容)

1)&#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;回答 - 使用您正在使用的当前方法,在下面:

2)&#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的关系功能并使用导航属性,以使您的代码更清晰(并且您的生活更轻松)。

希望这有帮助! :)