Не редактируются и не удаляются данные в БД, EF6 C# MVC

215
23 февраля 2018, 15:15

Добрый день! Подскажите как решить вопрос с записью в БД измененных данных или удалением их. Данные во view выводятся, в контроллер передаются, но изменений не происходит, выводит ошибку. Проблема где-то в контроллере когда пытаюсь изменить данные типа IList. В таком виде изменяются значения только свойств Customer, не IList. Как должен выглядеть код, чтобы все изменения учитывались?

Текст ошибки:

Attaching an entity of type 'CustomerApp.Models.Phone' failed because another entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any entities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the 'Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.

Модель:

public class Customer
{
    [Key]
    public int Id { get; set; }
    [Required]
    [DisplayName("Имя")]
    public string Name { get; set; }
    [Required]
    [DisplayName("Адрес")]
    public IList<Address> Addresses
    {
        get
        {
            return this._address;
        }
        set => this._address = value;
    }
    private IList<Address> _address = new List<Address>();
    [Required]
    [DisplayName("Телефон")]
    public IList<Phone> Phones
    {
        get
        {
            return this._phones;
        }
        set => this._phones = value;
    }
    private IList<Phone> _phones = new List<Phone>();
    [Required]
    [DisplayName("E-mail")]
    public IList<Email> Emails
    {
        get
        {
            return this._email;
        }
        set => this._email = value;
    }
    private IList<Email> _email = new List<Email>();
    [DisplayName("Обновлен")]
    public IList<ProfileUpdate> ProfileUpdates { get; set; }
    [DisplayName("Заметка")]
    public string Notes { get; set; }
    [DisplayName("Аккаунт")]
    public bool Active { get; set; } = true; // по умолчанию аккаунт "Действующий"
}
public class Email
{
    public enum emailTypes
    {
        Work,
        Home
    }
    [Key]
    public int Id { get; set; }
    [Required]
    public emailTypes Type { get; set; }
    [Required]
    [EmailAddress]
    [DisplayName("E-mail")]
    public string Value { get; set; }
    public IEnumerable<SelectListItem> EmailTypeSelectListItems
    {
        get
        {
            foreach (emailTypes type in Enum.GetValues(typeof(emailTypes)))
            {
                var selectListItem = new SelectListItem
                                         {
                                             Text = type.ToString(),
                                             Value = type.ToString(),
                                             Selected = this.Type == type
                                         };
                yield return selectListItem;
            }
        }
    }
}
public class Phone
{
    public enum phoneTypes
    {
        Work,
        Mobile
    }
    [Key]
    public int Id { get; set; }
    [Required]
    public phoneTypes Type { get; set; }
    [Required]
    [Phone]
    [DisplayName("Телефон")]
    public string Value { get; set; }
    public IEnumerable<SelectListItem> PhoneTypeSelectListItems
    {
        get
        {
            foreach (phoneTypes type in Enum.GetValues(typeof(phoneTypes)))
            {
                var selectListItem = new SelectListItem
                                         {
                                             Text = type.ToString(),
                                             Value = type.ToString(),
                                             Selected = this.Type == type
                                         };
                yield return selectListItem;
            }
        }
    }
}
public class ProfileUpdate
{
    [Key]
    public int Id { get; set; }
    public DateTime UpdateDateTime { get; set; }
}
public class Address
{
    public enum addressTypes
    {
        Visiting,
        Home
    }
    [Key]
    public int Id { get; set; }
    [Required]
    public addressTypes Type { get; set; }
    [Required]
    [DisplayName("Адрес 1")]
    public string Street1 { get; set; }
    [DisplayName("Адрес 2")]
    public string Street2 { get; set; }
    [Required]
    [DisplayName("Почтовый индекс")]
    public int PostalCode { get; set; }
    [Required]
    [DisplayName("Город")]
    public string Town { get; set; }
    public IEnumerable<SelectListItem> AddressTypeSelectListItems
    {
        get
        {
            foreach (addressTypes type in Enum.GetValues(typeof(addressTypes)))
            {
                var selectListItem = new SelectListItem
                                         {
                                             Text = type.ToString(),
                                             Value = type.ToString(),
                                             Selected = this.Type == type
                                         };
                yield return selectListItem;
            }
        }
    }
}

View:

<div class="form-horizontal">
    <hr />
    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
    @Html.HiddenFor(model => model.Id)
    @Html.HiddenFor(model => model.Active, true)
    <div class="form-group">
        @Html.LabelFor(model => model.Name, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group">
        @Html.LabelFor(model => model.Notes, new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.Notes, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Notes, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group">
        @Html.Label("Телефон", new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            <div id="phoneList">
                @for (var i = 0; i < Model.Phones.Count; i++)
                {
                    <div class="phoneRow">
                        @Html.DropDownList("Phones[" + i + "].Type", Model.Phones[i].PhoneTypeSelectListItems, new { @class = "phoneType form-control" })
                        @Html.TextBoxFor(model => Model.Phones[i].Value, new { placeholder = "Номер телефона", @class = "phoneNumber form-control" })
                        <a href="javascript:void(0);" class="remRowPhone"><span class="glyphicon glyphicon glyphicon-trash"></span>Удалить</a>
                    </div>
                }
            </div>
            <p>
                <a href="javascript:void(0);" class="addRowPhone"><span class="glyphicon glyphicon-plus"></span>Добавить номер</a>
            </p>
            @Html.ValidationMessageFor(model => model.Phones, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group">
        @Html.Label("Email", new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            <div id="emailList">
                @for (var i = 0; i < Model.Emails.Count; i++)
                {
                    <div class="emailRow">
                        @Html.DropDownList("Emails[" + i + "].Type", Model.Emails[i].EmailTypeSelectListItems, new { @class = "emailType form-control" })
                        @Html.TextBoxFor(model => Model.Emails[i].Value, new { placeholder = "Электропочта", @class = "emailValue form-control" })
                        <a href="javascript:void(0);" class="remRowEmail"><span class="glyphicon glyphicon glyphicon-trash"></span>Удалить</a>
                    </div>
                }
            </div>
            <p>
                <a href="javascript:void(0);" class="addRowEmail"><span class="glyphicon glyphicon-plus"></span>Добавить Email</a>
            </p>
            @Html.ValidationMessageFor(model => model.Emails, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group">
        @Html.Label("Адрес", new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            <div id="addressList">
                @for (var i = 0; i < Model.Addresses.Count; i++)
                {
                    <div class="addressRow">
                        @Html.DropDownList("Adresses[" + i + "].Type", Model.Addresses[i].AddressTypeSelectListItems, new { @class = "addressType form-control" })
                        @Html.TextBoxFor(model => Model.Addresses[i].PostalCode, new { placeholder = "Почтовый индекс", @class = "addressPostalCode form-control" })
                        @Html.TextBoxFor(model => Model.Addresses[i].Town, new { placeholder = "Город", @class = "addressTown form-control" })
                        @Html.TextBoxFor(model => Model.Addresses[i].Street1, new { placeholder = "Улица", @class = "addressStreet1 form-control" })
                        @Html.TextBoxFor(model => Model.Addresses[i].Street2, new { placeholder = "Номер дома или квартиры", @class = "addressStreet2 form-control" })
                        <a href="javascript:void(0);" class="remRowAddress"><span class="glyphicon glyphicon glyphicon-trash"></span>Удалить</a>
                    </div>
                }
            </div>
            <p>
                <a href="javascript:void(0);" class="addRowAddress"><span class="glyphicon glyphicon-plus"></span>Добавить Адрес</a>
            </p>
            @Html.ValidationMessageFor(model => model.Addresses, "", new { @class = "text-danger" })
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Сохранить" class="btn btn-default" />
        </div>
    </div>
</div>

Контроллер:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Edit(Customer customer)
    {
        if (!this.ModelState.IsValid)
        {
            return this.View(customer);
        }
        var result = await this.db.Customers.Include(a => a.Addresses).Include(a => a.Phones).Include(a => a.Emails).Include(a => a.ProfileUpdates).SingleOrDefaultAsync(a => a.Id == customer.Id).ConfigureAwait(false);
        if (result == null)
        {
            return this.HttpNotFound();
        }
        customer.ProfileUpdates = new[] { new ProfileUpdate { UpdateDateTime = DateTime.Now } };
        this.db.Entry(result).CurrentValues.SetValues(customer);
        await this.db.SaveChangesAsync().ConfigureAwait(false);
        return this.RedirectToAction("Index");
    }
Answer 1

После этих изменений все успешно редактируется и сохраняется.

Controller:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Edit(Customer customer)
    {
        if (!this.ModelState.IsValid)
        {
            return this.View(customer);
        }
        try
        {
            var result = await this.db.Customers.Include(a => a.Addresses).Include(a => a.Phones).Include(a => a.Emails).Include(a => a.ProfileUpdates).SingleOrDefaultAsync(a => a.Id == customer.Id).ConfigureAwait(false);
            if (result == null)
            {
                return this.HttpNotFound();
            }
            result.Name = customer.Name;
            result.Notes = customer.Notes;
            result.Active = customer.Active;
            result.Addresses = customer.Addresses;
            result.Emails = customer.Emails;
            result.Phones = customer.Phones;
            result.ProfileUpdates.Add(new ProfileUpdate() { UpdateDateTime = DateTime.Now });
            await this.db.SaveChangesAsync().ConfigureAwait(false);
        }
        catch (DbUpdateException /* ex */)
        {
            ModelState.AddModelError("", "Unable to save changes. " +
                                         "Try again, and if the problem persists, " +
                                         "see your system administrator.");
        }
        return this.RedirectToAction("Index");
    }
READ ALSO
ASP.NET.После релиза пропадают папки

ASP.NET.После релиза пропадают папки

Добрый вечерЕсть проект на asp

214
Ошибки Сборки Microsoft Visual Studio 2017

Ошибки Сборки Microsoft Visual Studio 2017

Каковым бы код у меня ни был, в любом случае у меня после нескольких раз отладки в Microsoft Visual Studio 2017 пишет, что возникли некие "ошибки сборки",...

276
Разбить строку на символы

Разбить строку на символы

Можно ли в языке C# когда вводишь строку "string", например: "Собака" - разделить его на буквы "C", "о", "б", "а", "к", "а"Я знаю по функцию "Split", но там надо...

192
Не работает массив из объектов класса [дубликат]

Не работает массив из объектов класса [дубликат]

На данный вопрос уже ответили:

191