Bobby Tables
Bobby Tables

Reputation: 3013

Identity Specification false Entity Code First

I have the fallowing 2 classes:

[Table("People")]
    public class Person : IPerson
    {
        [Key]
        [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public string FirstName { get; set; }

        public Person()
        {
            Results = new Collection<Result>();
        }
        public string LastName { get; set; }

        public string Name
        {
            get
            {
                return FirstName + " " + LastName;
            }
            set{}
        }

        public string Email { get; set; }
        public DateTime? LastModified { get; set; }
        public virtual ICollection<Result> Results { get; set; }
    }

and

[Table("UserProfile")]

    public class UserProfile : Person
    {
        public UserProfile()
        {
            Faculty = new Faculty();
            Projects = new Collection<Project>();
        }
        public string UserName { get; set; }
        public string CNP { get; set; }
        public virtual Faculty Faculty { get; set; }
        public virtual ICollection<Project> Projects { get; set; }
    }

Every time i use EF CodeFirst to generate my DB, and try too run the seed method i get an error. An error occurred while updating the entries. See the inner exception for details. System.Data.SqlClient.SqlException: Cannot insert explicit value for identity column in table 'UserProfile' when IDENTITY_INSERT is set to OFF. You can find more about it here Seeding Membership with custom data Entity framework

I found out that to fix it after running update-database from the package manager console i have to open the table in server explorer and set Idendtity Specification to false for the Id in the UsersProfile table, my question is can i do something to my model so that i won't have to this every time i regenerate my Db.

I tried the answer from here Identity specification set to false but because of the inheritance (i think) i get

Conflicting configuration settings were specified for property 'Id' on type 'Prometheus.Models.Person': 
    DatabaseGeneratedOption = None conflicts with DatabaseGeneratedOption = Identity

Thank you.

Upvotes: 0

Views: 3553

Answers (1)

Colin
Colin

Reputation: 22595

I'm not totally sure exactly what is happening here but I do know the UserProfile table is often created with a call to WebSecurity.InitializeDatabaseConnection rather than the migrations code and that's going to put in an IDENTITY field. So there is a conflict between WebSecurity and Entity Framework here.

Then you are adding inheritance into the picture and because you have specified table names it is Table per Type - and Entity Framework wants that to use a shared primary key. So it probably does not want the UserProfile table to have an IDENTITY field.

I think you hit the nail on the head when you said

UserProfile inherits from People, that's my problem

I would change that relationship so that Person has a UserProfile instead. I think that models the real world more accurately and if you ever have any people who aren't users it will be easier to make the relationship optional. Like this:

[Table("People")]
public class Person : IPerson
{
    //avoids virtual call in constructor
    private ICollection<Result> _Results;

    public Person()
    {
        _Results = new Collection<Result>();
    }

    //no annotations required. 
    //An int field named Id is a database generated key by convention
    public int Id { get; set; }

    //Person has a UserProfile (optional)
    public int? UserProfileID { get; set; }

    public UserProfile UserProfile { get; set; }

    //etc

    public virtual ICollection<Result> Results
    {
        get { return _Results; }
        set { _Results = value; }
    }
}

public class UserProfile : ModelBase
{
    //UserProfile is always related to a Person
    public int PersonID { get; set; }

    public UserProfile Person { get; set; }

    //etc
}

You will also find loads of stuff about preferring composition over inheritance.

Otherwise you need to dig in to the migrations to get the tables created in the way that supports TPT - but you should also be aware that switching identity on/off in migrations does not happen automatically.Perhaps you could create the UserProfile table in a migration instead of with WebSecurity.InitializeDatabaseConnection

Upvotes: 1

Related Questions