'ASP.NET Core - Entity Framework Core - Drop Down List - DbContext SaveChanges Issue

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 class="col-sm-3">
    <label for="type" class="form-label stacked-justify-left">Contact Type</label>

    <select asp-for="Client.ContactType.ID" asp-items="Model.ContactTypes" class="form-control" style="height:40px; width:180px">
        <option value="">-- Select Type --</option>
    </select>
    <span asp-validation-for="Client.ContactType.ID" class="text-danger font-weight-bold"></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.



Solution 1:[1]

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" class="form-control" style="height:40px; width:180px">
    <option value="">-- Select Type --</option>
</select>
<span asp-validation-for="Client.ContactTypeID" class="text-danger font-weight-bold"></span>

Reference

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1