使用多个表

时间:2017-01-27 21:47:45

标签: c# asp.net asp.net-mvc entity-framework code-first

大家好,所以我正在尝试使用asp.net mvc创建一个应用程序,该代码第一个数据库允许用户能够根据自己的意愿创建一个包含尽可能多的图像的博客文章。我正在尝试使用一个表中的图像路径和标题,另一个表中的正文文本以及图像路径的外键。所以我可以创建一个包含多个图像的帖子。这是我第一次使用多个表,当前我遇到这个行context.SaveChanges();在我尝试创建帖子并将其保存到数据库时保存方法。感谢您对此问题的任何帮助。

  

EntityFramework.dll中发生了'System.Data.Entity.Infrastructure.DbUpdateException'类型的异常,但未在用户代码中处理

     

其他信息:更新条目时发生错误。有关详细信息,请参阅内部异常

当我使用一个表时,我能够使程序正常工作,但它有这个问题:https://imgur.com/a/lQQ3Q

这是数据库图表:http://imgur.com/a/iJZGx

查询我试图制作但不确定在我的代码中使用的位置。

var query = db.PostModel.Where(x => x.PostID == PostId).Select(x => new
{
    PostID = x.PostID,
    ImageId = x.ImageModel.ImageId,
    ImagePath = x.ImageModel.ImagePath,
    Heading = x.PostModel.Heading,
    PostBody = x.PostModel.PostBody
}).FirstOrDefault();

我的节目

查看以创建帖子

@model Crud.Models.PostModel
....
@using (Html.BeginForm("Create", "Home", null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
    <form action="" method="post" enctype="multipart/form-data">
        @Html.LabelFor(model => model.ImageModel.ImagePath)
        <input id="ImagePath" title="Upload a product image" multiple="multiple" type="file" name="files" />
        @Html.LabelFor(model => model.Heading)
        <input id="Heading" title="Heading" name="Heading" />
        @Html.LabelFor(model => model.PostBody)
        <input id="PostBody" title="PostBody" name="PostBody" />
        <p><input type="submit" value="Create" /></p>
    </form>
}

查看以显示帖子

@model IEnumerable<Crud.Models.PostModel>
....  
@foreach (var item in Model)
{
    <div>@Html.DisplayFor(modelItem => item.Heading)</div>
    <div>@Html.DisplayFor(modelItem => item.PostBody)</div>
    <div><img class="img-thumbnail" width="150" height="150" src="/Img/@item.ImageModel.ImagePath" /></div>
}

模型

public partial class PostModel
{
    [Key]
    [HiddenInput(DisplayValue = false)]
    public int PostID { get; set; }
    public string Heading { get; set; }
    public string PostBody { get; set; }
    [ForeignKey("ImageModel")]
    public int ImageId { get; set; }
    public virtual ImageModel ImageModel { get; set; }
}

public class ImageModel
{
    [Key]
    public int ImageId { get; set; }
    public string ImagePath { get; set; }
    public string PostID { get; set; }
}

的DbContext

public class EFDbContext : DbContext
{
    public DbSet<SchoolNewsModel> SchoolNews { get; set; }
    public DbSet<PostModel> Posts { get; set; }
    public DbSet<ImageModel> Images { get; set; }
}

控制器

public ViewResult Display()
{
    return View(repository.Posts);
}
public ViewResult Create()
{
    return View("Create", new PostModel());
}
[HttpPost]
public ActionResult Create(PostModel Image, IEnumerable<HttpPostedFileBase> files)
{
    if (ModelState.IsValid)
    {
        foreach (var file in files)
        {
            PostModel post = new PostModel();
            if (file.ContentLength > 0)
            {
                file.SaveAs(HttpContext.Server.MapPath("~/Img/") + file.FileName);
                //  post.ImagePath = file.FileName;
                post.PostBody = post.PostBody;
                post.Heading = post.Heading;
            }
            repository.Save(post);
        }
    }
    return RedirectToAction("display");
}

public ViewResult PublicPostDisplay()
{
    return View(repository.Posts);
}

存储库

public IEnumerable<PostModel> Posts
{
    get { return context.Posts; }
}

public void Save(PostModel Image)
{
    if (Image.PostID == 0)
    {
        context.Posts.Add(Image);
    }
    else
    {
        PostModel dbEntry = context.Posts.Find(Image.PostID);
        if (dbEntry != null)
        {
            dbEntry.ImageModel.ImagePath = Image.ImageModel.ImagePath;
        }
    }
    context.SaveChanges();
}

1 个答案:

答案 0 :(得分:1)

您需要包含错误的完整详细信息。它的查看内部异常以获取详细信息,它将为您提供相关信息。但是,由于您的模型和关系不正确,这可能无关紧要。

您希望PostModel拥有多个ImageModel,因此您需要一对多关系,并且您的PostModel需求具有以下属性

public virtual ICollection<ImageModel> Images { get; set; }

并删除int ImageIdImageModel ImageModel属性。此外,ImageModel应包含public virtual PostModel Post { get; set; }

您创建新PostModel的POST方法随后变为

[HttpPost]
public ActionResult Create(PostModel post, IEnumerable<HttpPostedFileBase> files)
{
    if (!ModelState.IsValid)
    {
        return View(post);
    }
    foreach (var file in files)
    {
        if (file.ContentLength > 0)
        {
            file.SaveAs(HttpContext.Server.MapPath("~/Img/") + file.FileName);
            // Initialize a new ImageModel, set its properties and add it to the PostModel
            ImageModel image = new ImageModel()
            {
                ImagePath = file.FileName
            };
            post.Images.Add(image);
        }
    }
    repository.Save(post);
    return RedirectToAction("display");
}

但是您的代码还有许多其他问题需要解决。

  1. 首先,您的视图嵌套了无效的HTML表单 支持的。您需要删除内部<form>代码
  2. 您的编辑数据,因此请始终使用视图模型(请参阅What is ViewModel in MVC?PostVM将包含一个属性 IEnumerable<HttpPostedFileBase> Images并在视图中绑定它 使用@Html.TextBoxFor(m => m.Images, new { type = "file", multiple = "multiple" })
  3. 您根本没有验证,您的属性应包含 验证属性,例如,[Required]属性 HeadingBody。你需要包括 视图中的每个媒体资源均为@Html.ValidationMessageFor()
  4. 您输入的手动html不会为您提供双向模型绑定 并阻止任何客户端验证。始终使用HtmlHelper 生成表单控件的方法,例如, @Html.TextBoxFor(..)
  5. 不要仅使用文件名保存图像(多个用户可以 上传具有相同名称的文件并覆盖现有文件。一 选项是使用Guid作为文件名,并包含一个 string DisplayName中的其他媒体资源ImageModel。参考 this answer 这个方法的一个例子。