Метод редактирования не изменяет строку и не возвращает ошибку, объясняющую, почему в Entity Framework 6 - PullRequest
0 голосов
/ 24 июня 2019

В свободное время я работаю над веб-приложением, чтобы выучить EF6, и использовал учебник, использованный с https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application.

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

В моем случае, эта функция редактирования редактирует название и категорию ингредиента, но ни одна из них не изменяется. Даже если я напрямую скопирую код из учебника, он не будет работать.

К сожалению, при попытке поймать ошибки не выдаются. Я даже пытался использовать UpdateModel вместо TryUpdateModel, но это тоже ничего не дает. Я предполагаю, что это означает, что это работает, но мои строки никак не редактируются. Я пытался изменить свой код несколько раз, но безрезультатно.

Контроллер:

// PUT: Ingredient/
[HttpPut, ActionName("Index")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> EditIngredient(int? id, byte[] rowVersion)
{
    string[] fieldsToBind = new string[] { "Name", "Category", "RowVersion" };

    var ingredients = db.Ingredients.Select(i => i).OrderBy(s => s.Name);
    var categories = db.IngredientCategories;
    var ingredientIndexViewModel = new IngredientIndex
    {
        ingredients = await ingredients.ToPagedListAsync(1, MaxIngredientsPerPage),
        categories = await categories.ToListAsync()
    };

    if (id == null)
    {
        ErrorMessage = "No id found to update.";
        return View(ingredientIndexViewModel);
    }

    // Try and find the ingredient we're trying to update. If we haven't found anything, it's removed.
    var ingredientToUpdate = await db.Ingredients.FindAsync(id);
    if (ingredientToUpdate == null)
    {
        ErrorMessage = "Unable to save changes. The ingredient was deleted by another user.";
        return RedirectToAction("Index");
    }

    if (!TryUpdateModel(ingredientToUpdate, fieldsToBind))
    {
        ErrorMessage = "Unable to update model.";
        return RedirectToAction("Index");
    }

    try
    {
        // Try updating the row in the database.
        db.Entry(ingredientToUpdate).OriginalValues["RowVersion"] = rowVersion;
        await db.SaveChangesAsync();
    }

    // Concurrency error (rowversion doesn't match DB rowversion)
    catch (DbUpdateConcurrencyException ex)
    {
        var entry = ex.Entries.Single();
        var clientValues = (Ingredient)entry.Entity;

        clientValues.Category = await db.IngredientCategories.FindAsync(clientValues.CategoryId);

        // Add the original vlaues to the information modals
        ModelState.AddModelError("NameValidation", $"Current value: { ingredientToUpdate.Name }");
        ModelState.AddModelError("CategoryValidation", $"Current value: { ingredientToUpdate.Category.Name }");

        ErrorMessage = @"The record you attempt to edit has been modified by another user during your session.<br/>
            The original values have been added next to the input for reference.<br/>
            If you still want to edit this record, then press the ""Edit"" button again.";

        // Update the rowversion for the next edit. The user is fully aware now so he can update if he wants.
        ingredientToUpdate.RowVersion = ingredientToUpdate.RowVersion;

        // Add the form ingredient for display
        ingredientIndexViewModel.ingredient = clientValues;

        return View(ingredientIndexViewModel);
    }
    catch (RetryLimitExceededException)
    {
        ErrorMessage = "Unable to save changes. Try again, and if the problem persists, see your system administrator.";
        return View(ingredientIndexViewModel);
    }

    SuccessMessage = $"{ingredientToUpdate.Name} has been updated.";
    return RedirectToAction("Index");
}

Модель:

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Site.Models
{
    public class Ingredient
    {
        public int Id { get; set; }

        [StringLength(50, MinimumLength = 2, ErrorMessage = "Make sure the name of your ingredient is between {2} and {1} characters.")]
        [Required(ErrorMessage = "Please insert a valid name for your ingredient.")]
        [Index(IsUnique = true)]
        public string Name { get; set; }

        [DisplayFormat(NullDisplayText = "No category")]
        public IngredientCategory Category { get; set; }

        public int CategoryId { get; set; }

        [DataType(DataType.Date)]
        [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
        [Display(Name = "Date added")]
        public DateTime Date_Added { get; set; } = DateTime.Now;

        [Timestamp]
        public byte[] RowVersion { get; set; }
    }

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

        [StringLength(50, MinimumLength = 2, ErrorMessage = "Make sure the category is between {2} and {1} characters.")]
        [Required(ErrorMessage = "Please insert a valid category.")]
        [Index(IsUnique = true)]
        [Display(Name = "Category")]
        public string Name { get; set; }

        [Timestamp]
        public byte[] RowVersion { get; set; }
    }
}

ViewModel:

using System.Collections.Generic;
using Site.Models;
using PagedList;

namespace Site.ViewModels
{
    public class IngredientIndex
    {
        // Create / edit
        public Ingredient ingredient { get; set; }

        // List
        public IPagedList<Ingredient> ingredients { get; set; }
        public List<IngredientCategory> categories { get; set; }
    }
}

Ожидаемый результат будет рабочим методом. По крайней мере TryUpdateModel / UpdateModel вернет ошибку, но я не могу найти никаких ошибок. Если это помогает, кажется, что clientValues получает значения базы данных, а не значения клиента. Он должен получить клиентские значения, чтобы заполнить форму ими, но вместо этого принимаются значения базы данных.

1 Ответ

0 голосов
/ 26 июня 2019

try

ingredientToUpdate.YourPropertyName  = rowVersion;              /// set new value to 

db.Entry(ingredientToUpdate).State = EntityState.Modified;
await db.SaveChangesAsync();

Методы обновления данных с использованием EF см. здесь

...