0

For the following classes :

public Car 
{
    public int ID { get; set; }
    public string Brand {get; set; }
}

Normally when we do :

Car c = new Car { Brand = "Jaguar" } ; // Point A
context.Cars.Add(c); // Point B
context.SaveChanges() // Point C

At point B, the ID should remain 0, and an ID should only be assigned at point C. However, I have found that for one of my classes, an ID is assigned at point B and this results in this exception being thrown :

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

I have played with Fluent API and I'm 99% sure my relationships are correctly defined. I can't figure out why this DbSet tries to assign an ID for this entity.

Update

Thank you for your help, so here is a more detailed illustration of my situation :

public Car 
{
    public int ID { get; set; }
    public string Brand {get; set; }
    public int Driver1ID {get; set;}
    public Person Driver1 {get; set;}
    public int Driver2ID {get; set;}
    public Person Driver2 {get; set;}
}

public Person
{
   public int ID { get; set; }
   public string Name { get; set; }
}

And here is my fluent configuration :

modelBuilder.Entity<Car>().HasKey(x => x.ID);
            modelBuilder.Entity<Car>().Property(x => x.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); // Added following Igor's suggestion
            modelBuilder.Entity<Car>().HasRequired(x => x.Driver1).WithOptional().WillCascadeOnDelete(false);
            modelBuilder.Entity<Car>().HasRequired(x => x.Driver2).WithOptional().WillCascadeOnDelete(false);

Edit 2

Well, I have found that actually Migrations messed up. For some reason EF put the 2nd foreign key (Driver2), on the primary key column. This is why, DbSet.Add() was populating the ID column with a value that was actually the Driver 2 ID.

I really don't know why EF got confused like that. And the weird thing is that I didn't see this FK when I looked in SQL Management Studio. It looks like EF applied some relashionships that were not actually in the DB.

I reset the whole migrations (deleted the migration folder and the _migrationhistory table, then executed Enable-Migrations and Add-Migration Init in PowerShell), and I have been able to see the problematic lines in the initial migration file.

Or course I have modified them and It seems to have solved the problem.

tobiak777
  • 3,175
  • 1
  • 32
  • 44
  • possible duplicate of [Cannot insert explicit value for identity column in table 'table' when IDENTITY\_INSERT is set to OFF](http://stackoverflow.com/questions/1334012/cannot-insert-explicit-value-for-identity-column-in-table-table-when-identity) – markpsmith Feb 20 '15 at 11:10
  • @markpsmith No it isn't because it is not supposed to do an identity insert, I have already seen this question before posting – tobiak777 Feb 20 '15 at 11:14
  • @red2nb: Can you please post your FluentApi configuration? – milanio Feb 20 '15 at 11:23
  • @milanio Thank you for your support, I've just update my question to provide you the requested information – tobiak777 Feb 20 '15 at 11:32
  • The problem is probably public Person Driver1ID {get; set;}. This should probably be an int not a Person so this: public int Driver1ID {get; set;}. – Igor Feb 20 '15 at 11:35
  • Many apologises this is a typo from me, it is already an int – tobiak777 Feb 20 '15 at 11:36
  • Exactly as @Igor said. You have just created 4 links between Car & Person – milanio Feb 20 '15 at 11:36
  • @milanio Sorry, it was actually a typo when I wrote the question – tobiak777 Feb 20 '15 at 11:37

2 Answers2

0

In your fluent (and also declaritivly) mapping you can do specify if the ID is assigned by the database using Identity or if its not. If you specify that it IS assigned your code should not also assign it because you will get an exception. In fluent you can do it like this:

public Car 
{
    public int ID { get; set; }
    public string Brand {get; set; }
    public int Driver1ID {get; set;}
    public Person Driver1 {get; set;}
    public int Driver2ID {get; set;}
    public Person Driver2 {get; set;}
}

public Person
{
   public int ID { get; set; }
   public string Name { get; set; }
}


protected override void OnModelCreating(DbModelBuilder modelBuilder) { 
// ....
modelBuilder.Entity<Car>().HasKey(x => x.ID);
modelBuilder.Entity<Car>().Property(x => x.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); // set it on
modelBuilder.Entity<Car>().HasRequired(x => x.Driver1).WithMany().HasForeignKey(x => x.Driver1ID).WillCascadeOnDelete(false);
modelBuilder.Entity<Car>().HasRequired(x => x.Driver2).WithMany().HasForeignKey(x => x.Driver2ID).WillCascadeOnDelete(false);
// ....
}
Igor
  • 60,821
  • 10
  • 100
  • 175
  • Thanks for your help, when I do that I get the exception : A dependent property in a ReferentialConstraint is mapped to a store-generated column. – tobiak777 Feb 20 '15 at 11:22
  • Maybe you made one of your foreign keys an identity? This should only be used on the primary key so property Id of your Car class. – Igor Feb 20 '15 at 11:25
  • I updated the example to better fit your example. This is used in the OnModelCreating method of your DbContext. – Igor Feb 20 '15 at 11:29
  • Thank you again, but I was already using it on my Primary Key, please see my updated question. – tobiak777 Feb 20 '15 at 11:34
  • I added the FK to the model, that should work with your existing ids for driver1/2. – Igor Feb 20 '15 at 11:57
  • @red2nb - Hope it worked for you. Let me know if you have more questions or mark this as the answer to close the thread. Thanks. – Igor Feb 20 '15 at 13:45
  • Unfortunately it didn't solve my problem, but I will update my question because I found whre the problem comes from. – tobiak777 Feb 20 '15 at 15:00
-1

You can attribute the Id column with

public Car 
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public string Brand {get; set; }
}
TYY
  • 2,702
  • 1
  • 13
  • 14
  • 1
    The OP already has an identity column, That is their whole problem. – ProfK Feb 01 '17 at 18:47
  • Yes but by marking it as database generated that should have alleviated the problem. Note also I replied to the original question and at the time of answering the question stating that it was database generated was the answer to the question. More updates and discussion with the other answer continued. I don't think down voting my answer is accurate 1 year later. – TYY Feb 06 '17 at 17:36