EF核心:更新一对多关系相关实体ID

时间:2019-06-29 16:29:12

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

我是ASP.NET核心和EF核心的新手。请检查我的代码,让我知道我在做什么错。

** AuthorId违反外键约束。 **无法跟踪BookCategory实体,因为正在跟踪具有相同ID的另一个实例

  

图书模型

public class Book
    {
        public int BookId { get; set; }
        public string Title { get; set; }
        public double Price { get; set; }
        public int? Discount { get; set; }
        public string ImagePath { get; set; }
        public int? Stock { get; set; }

        public Author Author { get; set; }
        public int AuthorId { get; set; }

        public BookCategory Category { get; set; }
        public int? CategoryId { get; set; }

        public ICollection<JoinBookTag> BookTags { get; set; }
    }
  

BookCategory模型

public class BookCategory
    {
        public int Id { get; set; }

        [Display(Name = "Category Name")]
        public string CategoryName { get; set; }

        public ICollection<Book> Books { get; set; }

    }
  

作者模型

public class Author
    {
        public int AuthorId { get; set; }
        public string Name { get; set; }

        public ICollection<Book> Books { get; set; }
    }
  

BookController

        private readonly ApplicationDbContext _db;
        private readonly HostingEnvironment _hostingEnvironment;


        [BindProperty]
        public BookViewModel ViewModel { get; set; }
        public BookController(ApplicationDbContext db, HostingEnvironment host)
        {
            _db = db;
            _hostingEnvironment = host;
            ViewModel = new BookViewModel()
            {
                Book = new Models.Book(),
                Authors = _db.Authors.ToList(),
                BookCategories = _db.BookCategories.ToList(),
                Tags = _db.Tags.ToList()
            };
        }
  

......

[HttpGet]
        public IActionResult Edit(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }
            var book = _db.Books.Include(b => b.Category)
                        .Include(b => b.Author)
                        .SingleOrDefault(b => b.BookId == id);
            if (book == null)
            {
                return NotFound();
            }
            ViewModel.Book = book;
            return View(ViewModel);
        }

[HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(BookViewModel model, int? id)
        {
            if (id == null)
            {
                return NotFound();
            }
            if (id != model.Book.BookId)
            {
                return NotFound();
            }
            if (!ModelState.IsValid)
            {
                /*ViewModel.Book = model.Book;
                return View(ViewModel);*/
                var errors = ModelState.Select(x => x.Value.Errors)
                           .Where(y => y.Count > 0)
                           .ToList();
                return Json(new { errors });
            }
            var dbModel = _db.Books.Include(b => b.Category).Where(b => b.BookId == id).FirstOrDefault();

            var file = HttpContext.Request.Form.Files;
            if (file.Count > 0)
            {
                var RootDirectory = _hostingEnvironment.WebRootPath;
                var extension = Path.GetExtension(file[0].FileName);
                var filePath = Path.Combine(DataContext.ImageDirectory, model.Book.BookId + extension);
                using (var fileStream = new FileStream(Path.Combine(RootDirectory, filePath), FileMode.Create))
                {
                    file[0].CopyTo(fileStream);
                }

                dbModel.ImagePath = @"/" + filePath;
            }
            dbModel.AuthorId = model.Book.AuthorId;
            dbModel.CategoryId = model.Book.CategoryId;
            dbModel.Discount = model.Book.Discount;
            dbModel.Price = model.Book.Price;
            dbModel.Stock = model.Book.Stock;
            dbModel.Title = model.Book.Title;

            await _db.SaveChangesAsync();
            return RedirectToAction(nameof(Index));

        }

1 个答案:

答案 0 :(得分:1)

您需要在模型内的id属性上添加key属性。

接下来需要更新的是告诉_db,然后先更新您的实体,然后才保存更改。

为什么要使用异步并等待?这些控制器动作会减慢UI速度吗?

您还可以发布图书浏览模型吗?

您的操作方法在某些地方是错误的。如果您需要更详细的建议,请告诉我。

    [HttpGet]
    public IActionResult Edit(int? id)
    { 
       //Give this a name other than view model for example BookViewModel
       ViewModel model = new ViewModel();

        if (id == null)
        {
            return NotFound();
        }

        var book = _db.Books.Include(b => b.Category)
                    .Include(b => b.Author)
                    .SingleOrDefault(b => b.BookId == id);

        if (book == null)
        {
            return NotFound();
        }

        model.Book = book;

        return View(model);
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Edit(BookViewModel model, int? id)
    {
        if (id == null || id != model.Book.BookId)
        {
            return NotFound();
        }

        if (ModelState.IsValid)
        {
            var dbModel = _db.Books.Include(b => b.Category).Where(b => b.BookId == id).FirstOrDefault();

        var files = HttpContext.Request.Form.Files;
        if (files.Any())
        {
            var RootDirectory = _hostingEnvironment.WebRootPath;
            var extension = Path.GetExtension(files[0].FileName);
            var filePath = Path.Combine(DataContext.ImageDirectory, model.Book.BookId + extension);
            using (var fileStream = new FileStream(Path.Combine(RootDirectory, filePath), FileMode.Create))
            {
                file[0].CopyTo(fileStream);
            }

            dbModel.ImagePath = @"/" + filePath;
        }

        dbModel.AuthorId = model.Book.AuthorId;
        dbModel.CategoryId = model.Book.CategoryId;
        dbModel.Discount = model.Book.Discount;
        dbModel.Price = model.Book.Price;
        dbModel.Stock = model.Book.Stock;
        dbModel.Title = model.Book.Title;

        await _db.Books.UpdateAsync(dbModel);
        await _db.SaveChangesAsync();

        return RedirectToAction(nameof(Index));

        }

        return View(model);

    }