Kira
Kira

Reputation: 27

'Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.'

I am sending Customer and all MembershipTypes to the Edit view from Customer Controller because I need both, if you can tell me how to send both in VIEW not in ViewBag.Message as well as why my app throws error everytime I edit an item please

My customer class which has a many - to one relationship with membershipType class:

 public class Customer
    {
        public Customer()
        {
            this.Movies = new HashSet<Movie>();
        }
        public int id { get; set; }
        [Required]
        [StringLength(255)]
        public String Name { get; set; }
        public bool IsSubscribedToNewsletter { get; set; }
        public int CurrentMembershipTypeId { get; set; }
        public MembershipType CurrentMembershipType { get; set;}
        public ICollection<Movie> Movies { get; set; }
    }

My MembershipType class:

public class MembershipType
    {
        public int Id { get; set; }
        public short SignupFee { get; set; }
        public byte DurationInMonths { get; set; }
        public byte DiscountRate { get; set; }
        public ICollection<Customer> Customers { get; set; }

        // public virtual ICollection<Movie> Movie { get; set; }
    }

My CustomerController: get Function for customer Edit:

  public ActionResult Edit(int id)
        {
            Customer customer = new Customer();
            customer = iCustomerRepository.GetCustomerByID(id);
            var membershipTypes = iMembershipTypeRepository.GetMembershipTypes();
            ViewBag.Message = membershipTypes;
            return View(customer);
        }

Post action for Customer Edit:

[HttpPost]
        public ActionResult Edit(Customer customer)
        {
            Customer Customer = new Customer();
            Customer.id = customer.id;
            Customer.Name = customer.Name;
            Customer.IsSubscribedToNewsletter = customer.IsSubscribedToNewsletter;
            Customer.CurrentMembershipTypeId = customer.CurrentMembershipTypeId;
            iCustomerRepository.UpdateCustomer(Customer);
            iCustomerRepository.Save();
            return RedirectToAction("Customer");
        }

Customer Form Edit View:

<form action="/Customer/Edit" method="post">
    <table>
        <tr>
            <td>Id:</td>
            <td><label for="CustomerId">ID:</label></td>
            <td><input id="CustomerId" type="number" name="CustomerId" value="@Model.id" /></td>
        </tr>
        <tr>
            <td>Name:</td>
            <td><input id="CustomerName" type="text" name="CustomerName" value="@Model.Name" /></td>
        </tr>
        <tr>
            <td>IsSubscribedToNewLetter:</td>
            <td><input id="CustomerisSubscribedToNewsLetter" type="text" name="CustomerisSubscribedToNewsLetter" value="@Model.IsSubscribedToNewsletter" /></td>
        </tr>
        <tr>
            <td>MembershipType:</td>
            <td>
                <select id="MembershipTypeId" name="MembershipTypeId">
                    @foreach (var membershipType in @ViewBag.Message)
                    {
                        <option [email protected]>
                            @membershipType.Id
                        </option>
                    }
                </select>
            </td>
        </tr>
    </table>
    <input type="submit" value="save" />
</form>

Customer repository class:

namespace WebApplication2.Repositories.CustomersRepositories

{

public class CustomerRepository : ICustomerRepository, IDisposable

{

    private CustomerContext context;



    public CustomerRepository(CustomerContext context)

    {

        this.context = context;

    }

    //public short GetMembershipTypeSignupFee()
    //{
    //    var Customers = context.Customers.ToList();
    //    foreach (var customer in Customers)
    //    {
    //       return  customer.CurrentMembershipType.SignupFee;
    //    }

    //}

    public IEnumerable<Customer> GetCustomers()

    {

        return context.Customers.ToList();

    }

    public Customer GetCustomerByID(int Id)

    {

        return context.Customers.Find(Id);

    }

    public void InsertCustomer(Customer customer)

    {

        context.Customers.Add(customer);

    }

    //public void InsertMany()

    //{

    //    context.Customers.AddRange(context.Customers);

    //}

    public void DeleteCustomer(int Id)

    {

        Customer customer = context.Customers.Find(Id);

        context.Customers.Remove(customer);

    }

    public void DeleteAllCustomers()

    {

        context.Customers.RemoveRange(context.Customers);

        context.SaveChanges();

    }

    public void UpdateCustomer(Customer customer)

    {

        context.Entry(customer).State = EntityState.Modified;

    }

    public void Save()

    {

        context.SaveChanges();

    }



    private bool disposed = false;

    protected virtual void Dispose(bool disposing)

    {

        if (!this.disposed)

        {

            if (disposing)

            {

                context.Dispose();

            }

        }

        this.disposed = true;

    }



    public void Dispose()

    {

        Dispose(true);

        GC.SuppressFinalize(this);

    }

}

}

Upvotes: 1

Views: 464

Answers (1)

tmaj
tmaj

Reputation: 34947

Since you haven't shown the repository method, this is a guess.

iCustomerRepository.UpdateCustomer(Customer); tries to add a new customer and database rightly rejects it because a record with the given id already exists.

The repository method need to load the existing customer and then change it's properties. BTW. It's common to have SaveChanges inside the repository call rather then the controller calling it.

Something like the following.

var Upadate(Customer customer) {
    // Authorization code here maybe

    using( var context = ... ) {
       var dbCustomer = c.Customers.FirstOrDefault( c => c.Id = customer.id );
       if( dbCustomer == null ) throw new KeyNotFoundException("Customer not found!");
       dbCustomer.A = ...;
       dbCustomer.B = ...;


       context.SaveChanges();
}

I would encourage you to use names starting with a lowercase letter for variables.

Upvotes: 1

Related Questions