2017-01-27 4 views
0

Привет всем, поэтому я пытаюсь создать приложение с использованием asp.net mvc с первой базой данных кода, которая позволяет пользователям создавать запись в блоге с таким количеством изображений, как они хотят. Я в настоящее время пытается иметь путь изображения в одной таблице и заголовок, основной текст в другой таблице вместе с внешним ключом к пути к изображению. Так что я могу создать одно сообщение с несколькими изображениями. Это мой первый раз, используя несколько таблиц, и в настоящее время я получаю сообщение об ошибке, когда он достигает этого контекста строки. SaveChanges(); в методе сохранения, когда я пытаюсь создать сообщение и сохранить его в db. Благодарим вас за помощь в решении этой проблемы.Исправление обновления с использованием нескольких таблиц

Исключение типа «System.Data.Entity.Infrastructure.DbUpdateException» произошло в EntityFramework.dll, но не был обработан в пользовательском коде

Дополнительная информация: Произошла ошибка при обновлении записей. Смотрите внутреннее исключение для деталей

я был в состоянии получить программу на работу, когда я использую одну таблицу, но имел этот вопрос: 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> 
} 

View для отображения Сообщений

@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); 
} 

Repository

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(); 
} 
+0

Не уверен, что я понимаю, что ваши желания достичь. вы хотите сохранить один 'PostModel', который содержит несколько изображений (в этом случае вам нужно отдельная таблица для путей изображения с FK к идентификатору 'PostModel'? –

+0

* и пути изображений, хранящиеся во второй таблице, и дают каждый внешний ключ ImageId *. Очень расплывчато. Не используйте слова. Показать диаграмму db. –

+0

Привет, Стивен, да, сейчас у меня есть одна таблица, и я спрашиваю, как я могу сделать так, чтобы у меня была вторая таблица, в которой хранятся изображения. так что, когда пользователь создает сообщение, он создает сообщение в таблице сообщений вместе с внешним ключом, который соединяет каждое изображение с этим сообщением. Извините, если я плохо объясняю, что раньше я работал с несколькими таблицами. Как вы можете видеть в сообщении, у меня есть вторая таблица, прокомментированная, так как я не уверен, как ее использовать, и я хочу опубликовать, как она работает в настоящее время, чтобы люди могли мне посоветовать об изменениях и способах работы запросов и т. Д., Спасибо за вашу помощь – WellThisIsAkward

ответ

1

Вам необходимо включить полную информацию об ошибке. Его См. Внутреннее исключение для деталей, которое предоставит вам соответствующую информацию. Однако это, вероятно, не имеет значения, поскольку ваши модели и отношения неверны.

Вы хотите PostModel иметь несколько ImageModel так что вам нужен один-многим и ваши PostModel потребности обладают свойством

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

и удалить Int ImageId и ImageModel ImageModel свойства.Кроме того, ImageModel должен содержать public virtual PostModel Post { get; set; }

Вашего метода POST для создания нового PostModel становится

[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. You не имеют никакой валидации, и ваши свойства должны включать атрибуты валидации , например, атрибут [Required] на Heading и Body. Вам необходимо включить @Html.ValidationMessageFor() для каждого объекта недвижимости.
  4. Ваш ручной html для входов не даст вам двухстороннюю привязку модели и предотвратит любую проверку на стороне клиента. Всегда используйте методы HtmlHelper для создания элементов управления формой, например. @Html.TextBoxFor(..)
  5. Не сохранять изображение только с именем файла (несколько пользователей могут загружать файлы с тем же именем и перезаписывать существующие файлы. Один вариант заключается в использовании Guid для имени файла, и включают в себя дополнительное свойство string DisplayName в ImageModel См. this answer для примера такого подхода.
+0

Я пробовал обновлять свою программу с вашими рекомендациями, но теперь я получаю исключение с нулевой ссылкой для файлов для каждого метода в методе создания сообщения. Также я знаю, что ошибался, пытаясь реализовать View Model, поскольку я не думаю, что я хочу, чтобы public int CreatePostId {get; задавать; } общественный виртуальный ICollection Images {get; задавать; } public virtual PostModel Post {get; задавать; } в моей модели. Спасибо за любую помощь. – WellThisIsAkward

+0

Ссылка только начала происходить, когда я поменялся с этого в это @ Html.TextBoxFor (модель => model.ImagePath, new {type = "file", multiple = "multiple", name = "files"}), но разве они не совпадают? – WellThisIsAkward

+0

Сначала вы не можете просто изменить вопрос и аннулировать мой ответ - я отбросил ваши изменения. Если у вас возникла новая проблема, вы можете задать новый вопрос о добавлении нового кода, который вы попробовали. –

Смежные вопросы