4

Using EF6 code-first :

My entity :

public class Symbol
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.None)]
    public int Id
    {
        get; set; 
    }

    public string Name { get; set; }
}

Error :

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

The common solution for this when googling the problem is setting DatabaseGeneratedOption.Identity.

  1. This does not make sense now that I can't tell the DB not to generate the Identity for me

  2. It results in a weird side effect. It is generating a running identity, running from where ever I left off. Where even if I delete all the entities in the table.

Scenario :

   1) inserting   { 44, "s1"} , { 55, "s2"} , { 52, "s3"}          
      In DB : {1,"s1"} {2,"s2"} {3,"s3"} 
   2) delete all symbols   
   3) inserting   { 44, "s1"} , { 55, "s2"} , { 52, "s3"}          
      In DB : {4,"s1"} {5,"s2"} {6,"s3"} 

I'm guessing if I set Identity insert on before each insert, this might work.

Like in this answer only on each insert

Is there any built in way to insert identity with out having to set identity insert on manually on each insert ?

EDIT :

I've also tried something inspired by the link above :

    public void InsertRange(IEnumerable<TEntity> entities)
    {
        _context.IdentityInsert<TEntity>(true);

        _dbSet.AddRange(entities);
        _context.SaveChanges();

        _context.IdentityInsert<TEntity>(false);
    }


    public static string GetTableName<T>(this DbContext context) where T : class
    {
        ObjectContext objectContext = ((IObjectContextAdapter) context).ObjectContext;
        return objectContext.GetTableName<T>();
    }

   public static string GetTableName<T>(this ObjectContext context) where T : class
    {
        string sql = context.CreateObjectSet<T>().ToTraceString();
        Regex regex = new Regex(@"FROM\s+(?<table>.+)\s+AS");
        Match match = regex.Match(sql);

        string table = match.Groups["table"].Value;
        return table;
    }

    public static void IdentityInsert<T>(this DbContext context ,bool on) where T : class
    {
        if (on)
        {
            context.Database.ExecuteSqlCommand(string.Concat(@"SET IDENTITY_INSERT ", context.GetTableName<T>(), @" ON"));
        }
        else
        {
            context.Database.ExecuteSqlCommand(string.Concat(@"SET IDENTITY_INSERT ", context.GetTableName<T>(), @" OFF"));
        }
    }

It didn't work

EDIT 2 :

Well droping the DB completely and then setting it with

          [Key]
          [DatabaseGeneratedAttribute(DatabaseGeneratedOption.None)]

did the trick, the thing is i got important data in that DB and can't afford to drop it on each change. For that I use migrations after a migration the problem emerged .

EDIT :

This seems to explain the issue

Migrations don't support identity change.

Probably having the primary key defined before and then depending on the migration when i change its identity settings doesn't work.

The moral of the story. Be sure of your identities on the beginning if not drop create or do the custom migration from the link.

Community
  • 1
  • 1
eran otzap
  • 12,293
  • 20
  • 84
  • 139
  • If your key is not generate dby the database then you should provide a value for that key. – CodeNotFound Nov 06 '16 at 16:14
  • Yes yes i should. And am. It gives me an error you can find it under the part which says "ERROR :" in the question above – eran otzap Nov 06 '16 at 16:15
  • So you should also remove identity insertion on the table into database. How do you generate the tables ? – CodeNotFound Nov 06 '16 at 16:18
  • It's EF code first . – eran otzap Nov 06 '16 at 16:28
  • So you generate your DB from the Code First or the databse already exists? – CodeNotFound Nov 06 '16 at 16:37
  • It does not yet exist. it exists after the first time i used it.. " It's already there when i attempt to insert stuff into it, if that's the question – eran otzap Nov 06 '16 at 16:40
  • 2
    Try to first drop that database completely and generate from scratch. Ensure that database does _not_ have Id column as identity. – Evk Nov 06 '16 at 16:50
  • You r problem is really weird. You deactivated the Identiy insertion and genrate your DB from your model then you tell that in the table Identiy is activated? Don't get your problem. – CodeNotFound Nov 06 '16 at 16:51
  • The problem : I want to insert my own Identity . for this iv'e done : [Key] [DatabaseGeneratedAttribute(DatabaseGeneratedOption.None)] public int Id { get; set; } Then i get an error regarding the identity insert . that's the entire deal. – eran otzap Nov 06 '16 at 16:54
  • So you should use `[DatabaseGenerated(DatabaseGeneratedOption.Computed]` Instead of `[DatabaseGenerated(DatabaseGeneratedOption.None)]` – CodeNotFound Nov 06 '16 at 17:08
  • Why ? None - The database does not generate values. Identity - The database generates a value when a row is inserted. Computed - The database generates a value when a row is inserted or updated. – eran otzap Nov 06 '16 at 17:14

1 Answers1

1

Turn off identity in db and manage your key values in your Code.... This is the best approach

  • could you elaborate ? that seems like what i'm attempting to do. i am giving values to my keys . i can't insert them because of the identity insert issue. – eran otzap Nov 06 '16 at 16:28