身份规范虚假实体代码优先

时间:2014-01-15 17:11:54

标签: c# asp.net asp.net-mvc entity-framework ef-code-first

我有2个课程:

[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; }
    }

[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; }
    }

每次我使用EF CodeFirst生成我的数据库,并尝试运行种子方法时我会收到错误。 更新条目时发生错误。有关详细信息,请参阅内部异常System.Data.SqlClient.SqlException:当IDENTITY_INSERT设置为OFF时,无法在表'UserProfile'中为identity列插入显式值。您可以在此处找到有关它的更多信息Seeding Membership with custom data Entity framework

我发现在从包管理器控制台运行update-database后要修复它我必须在服务器资源管理器中打开表,并为 ID Idendtity Specification设置为false在 UsersProfile 表格中,我的问题是我可以对我的模型做些什么,这样每次重新生成我的Db时我都不会这样做。

我在这里尝试了答案Identity specification set to false,但由于继承(我认为),我得到了

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

谢谢。

1 个答案:

答案 0 :(得分:1)

我并不完全确定这里发生了什么,但我确实知道UserProfile表通常是通过调用WebSecurity.InitializeDatabaseConnection创建的,而不是迁移代码,而且会放入IDENTITY领域。因此,此处WebSecurity与实体框架之间存在冲突。

然后您将继承添加到图片中,因为您指定了表名称Table per Type - 并且实体框架希望使用shared primary key。因此,它可能不希望UserProfile表具有IDENTITY字段。

当你说

时,我觉得你的头上钉了一针
UserProfile inherits from People, that's my problem

我会改变这种关系,以便Person 有一个 UserProfile。我认为更准确地模拟现实世界,如果你有任何不是用户的人,那么将关系变得更加容易。像这样:

[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
}

您还会发现大量关于preferring composition over inheritance的内容。

否则,您需要深入了解迁移以获取以支持TPT的方式创建的表 - 但您还应该知道switching identity on/off in migrations does not happen automatically。也许您可以创建UserProfile表迁移而不是WebSecurity.InitializeDatabaseConnection