Home > Software design >  ASP.NET Core - Entity Framework Core - Drop Down List - DbContext SaveChanges Issue
ASP.NET Core - Entity Framework Core - Drop Down List - DbContext SaveChanges Issue

Time:05-16

I'm new to using EF as well as ASP.NET Core. I'm working on a simple web application and I am getting an error when I go to save a new record. When the DbContext.SaveChanges() gets called, I get an error that states:

"Cannot insert explicit value for identity column in table 'ContactTypes' when IDENTITY_INSERT is set to OFF."

I understand exactly what the message means and why I am getting it. Based on that message, EF is trying to insert a record into the ContactTypes table and since that table does not allow inserting primary key value, it gives that error. The ContactTypes table has a set of fixed records that will likely not change. The records from the ContactTypes table are used to populate a drop down list (HTML select element). That functionality works fine and when the user selects the desired option and then tries to save the parent (Client) record, EF wants to insert a new record into the ContactTypes table, which is unnecessary. When EF Core created the database, a "ContactTypeID" field was added to the Clients table, which should hold the ID for the ContactType selected.

Client Database Table

Below are my classes

public class Client
{
    public int ID { get; set; }

    public Person Person { get; set; }// = new Person();
    public ContactType ContactType { get; set; }// = new ContactType();//Client or Inquiry

    //other properties removed for brevity
}

public class ContactType
{
    public int ID { get; set; }

    [StringLength(20)]
    public string ContactTypeDescription { get; set; } //typically either Client or Inquiry
}

public class Person
{
    public int ID { get; set; }

    [Required, StringLength(50)]
    public string FirstName { get; set; } = "N/A";

    [Required, StringLength(50)]
    public string LastName { get; set; } = "N/A";

    //other properties removed for brevity

}   

Here's my OnModelCreating method:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        //setup our relationships
        modelBuilder.Entity<Client>()
            .HasOne(c => c.Person);

        modelBuilder.Entity<Client>()
            .HasOne(c => c.ContactType)
            .WithMany();


        //create our other supporting tables and initialize data if necessary
        modelBuilder.Entity<Person>().ToTable("People");

        modelBuilder.Entity<Person>().HasData(new Person { ID = 1, FirstName = "N/A", LastName = "N/A" });


        modelBuilder.Entity<ContactType>()
                    .ToTable("ContactTypes"); 

        modelBuilder.Entity<ContactType>().HasData(new ContactType { ID = 1, ContactTypeDescription = "Not Specified" },
                                                    new ContactType { ID = 2, ContactTypeDescription = "Inquiry" },
                                                    new ContactType { ID = 3, ContactTypeDescription = "Client" });

    }

Here is my markup for the HTML select

<div >
    <label for="type" >Contact Type</label>

    <select asp-for="Client.ContactType.ID" asp-items="Model.ContactTypes"  style="height:40px; width:180px">
        <option value="">-- Select Type --</option>
    </select>
    <span asp-validation-for="Client.ContactType.ID" ></span>
</div>

So I'm not sure how to tell EF Core not add records to the ContactTypes table when saving the Client entity information. If other information is needed, please ask and I will supply. Any help is appreciated.

CodePudding user response:

Probably Client class should be:

public class Client
{
    public int ID { get; set; }

    public Person Person { get; set; }// = new Person();

    public int ContactTypeID { get; set; }

    public ContactType ContactType { get; set; }// = new ContactType();//Client or Inquiry
}

public class ContactType
{
    public int ID { get; set; }

    [StringLength(20)]
    public string ContactTypeDescription { get; set; } //typically either Client or Inquiry

    public IList<Client> Clients { get; set; }
}
modelBuilder.Entity<Client>()
            .HasOne(c => c.ContactType)
            .WithMany()
            .HasForeignKey(c => c.ContactTypeId);

And modify the View as:

<select asp-for="Client.ContactTypeID" asp-items="Model.ContactTypes"  style="height:40px; width:180px">
    <option value="">-- Select Type --</option>
</select>
<span asp-validation-for="Client.ContactTypeID" ></span>

Reference

  1. Conventions in Entity Framework Core
  2. One-to-Many Relationship Conventions in Entity Framework Core
  • Related