#c# #asp.net #asp.net-mvc
#c# #asp.net #asp.net-mvc
Вопрос:
Я использую Visual Studio и следовал инструкциям по созданию базы данных фильмов Model-View-Controller. Ссылка на учебное пособие: https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/start-mvc?view=aspnetcore-5.0amp;tabs=visual-studio
Моя цель: заменить имена столбцов, которые появляются при запуске приложения.
В папке Models находится файл C # с именем Movie.cs. Он содержит класс Movie. Адаптируя программу для своих целей, я внес следующие изменения:
- Название на имя
- Дата выпуска на сегодняшний день
- Жанр электронной почты
- Цена контракта
Я включаю код из файла Movie.cs ниже:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
namespace MvcMovie.Models
{
public class Movie
{
public int ID { get; set; }
public string Name { get; set; }
[DataType(DataType.Date)]
public DateTime Date { get; set; }
public string Email { get; set; }
public decimal Contract { get; set; }
}
}
После внесения этих изменений я открыл папку Views и внутри нее открыл папку Movies. Папка Movies содержит файлы:
- create.cshtml
- удалить.cshtml
- details.cshtml
- edit.cshtml
- index.cshtml
Каждый из этих файлов содержал ссылки на название, дату выпуска, жанр и цену. Поэтому я обновил каждое из них до их нового имени, чтобы оно соответствовало названиям Movie.cs.
Ожидаемые результаты: я ожидал, что приложение отобразит новые имена столбцов (имя, дата, адрес электронной почты, контракт).
Фактические результаты: при сохранении и запуске домашняя страница открывается нормально, но когда я нажимаю, чтобы перейти на страницу фильмов, я получаю следующую ошибку:
При обработке запроса произошло необработанное исключение. Исключение SQLiteException: ошибка SQLite 1: «нет такого столбца: m.Contract». Microsoft.Data.Sqlite.Исключение SQLiteException.ThrowExceptionForRC(int rc, sqlite3 db)
На странице ошибок внутреннего сервера указано (предположительно) местоположение (выделено жирным шрифтом ниже) проблемы и немного красного текста, чтобы помочь мне точно определить проблему (КРАСНЫЙ ->):
MvcMovie.Контроллеры.MoviesController.Index() в MoviesController.cs
_context = context;
}
//End of Constructor
// GET: Movies
public async Task<IActionResult> Index()
{
RED -> return View(await _context.Movie.ToListAsync());
}
// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
Что я пробовал:
Я дважды проверил, что правильно обновил все имена в файле Movie.cs и в файлах Create, Delete, Details, Edit, Index.
Я также попытался зайти в папку Controllers и обновить файл MoviesController.cs новыми именами (имя, дата, адрес электронной почты, контракт). Ниже я включил содержимое файла MoviesController.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using MvcMovie.Data;
using MvcMovie.Models;
namespace MvcMovie.Controllers
{//Constructor using D.I. to inject database context into the controller
public class MoviesController: Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
//End of Constructor
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.ID == id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
// GET: Movies/Create
public IActionResult Create()
{
return View();
}
// POST: Movies/Create
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("ID,Name,Date,Email,Contract")] Movie movie)
{
if (ModelState.IsValid)
{
_context.Add(movie);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(movie);
}
// GET: Movies/Edit/5
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie.FindAsync(id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
// POST: Movies/Edit/5
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, [Bind("ID,Name,Date,Email,Contract")] Movie movie)
{
if (id != movie.ID)
{
return NotFound();
}
if (ModelState.IsValid)
{
try
{
_context.Update(movie);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!MovieExists(movie.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction(nameof(Index));
}
return View(movie);
}
// GET: Movies/Delete/5
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.ID == id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
// POST: Movies/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var movie = await _context.Movie.FindAsync(id);
_context.Movie.Remove(movie);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool MovieExists(int id)
{
return _context.Movie.Any(e => e.ID == id);
}
}
}
То, что я пробовал, не изменяет ошибку. Приложение работало нормально до того, как я обновил имена во всех файлах. Я очень признателен за любую помощь, которую кто-либо может предоставить.
Комментарии:
1. Если я правильно понял, вам нужно добавить миграцию и обновить базу данных. На данный момент ваши изменения в модели не отражают структуру таблицы базы данных.
2. Чтобы прояснить это, добавьте еще одну миграцию. Не удаляйте старый. Затем выполните обновление базы данных
3. Похоже
Movie
, класс сопоставлен с таблицей базы данных, а его свойства сопоставлены со столбцами таблицы. Это означает, что имя таблицы / имя класса и имена свойств / имена столбцов должны совпадать. Вы меняете имена свойств, что приводит к генерации SQL-запросов с этими именами столбцов, и эти новые имена не найдены в таблице базы данных. вот почему вы получаете эту ошибку. Вы просто хотите изменить то, что отображается в пользовательском интерфейсе? или вы также хотите изменить имена столбцов в базе данных?4. @RobWhite Спасибо!
5. @ChetanRanpariya Я был бы не против просто изменить то, что отображается в пользовательском интерфейсе, и оставить имена столбцов прежними, если это будет проще. Не могли бы вы порекомендовать правильный способ сделать это?
Ответ №1:
Когда вы сделаете это, вам придется удалить и заново создать базу данных — в базе данных все еще есть старые имена. Другой способ — использовать миграции code first и добавлять миграции, миграции исправят имена (переименуют их) при их создании — еще одна вещь, которую вы можете попробовать, это добавить атрибут аннотации данных к свойству, например :
[Display(Name = "Email")]
public string Email { get; set; }