Reputation: 3013
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
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