Can Poyrazoğlu
Can Poyrazoğlu

Reputation: 34830

Why is Entity Framework creating an extra column that doesn't map to any field and is always null?

I have my POCO set up like this:

public class Notification : BaseClass
{

    public User Receiver { get; set; }

    [Required, Index]
    public long ReceiverID { get; set; }

    public virtual User ContextualUser { get; set; }

    public long? ContextualUserID { get; set; }

    public virtual User Actor { get; set; }

    public long? ActorID { get; set; }

    public string Content { get; set; }

    public string Uri { get; set; }

    [Required]
    public string Type { get; set; }

}

My base class has only three properties: ID, CreateDate, and IsDeleted, none are related to User class:

public abstract class BaseClass
{
    [Key]
    public long ID { get; set; }

    [Required]
    public DateTime CreateDate { get; set; }

    public bool IsDeleted { get; set; }

    public BaseClass()
    {
        CreateDate = DateTime.UtcNow;
    }
}

However, Entity Framework creates an extra column, User_ID, which is always null, as seen below:

enter image description here

It doesn't apparently map to anything. None of my other entities (either deriving from the same base class or not) have this phantom column. Why is this column created? I am on EF 6.1.3 code-first with SQL Azure.

UPDATE: I've also ran update-database in PM console but nothing has changed, I still have this column.

UPDATE 2: There is even an index and a foreign key defined on column. I've tried dropping it (it's not a live app yet) but it's being referenced by an index:

alter table notifications drop column User_ID

Msg 5074, Level 16, State 1, Line 1
The index 'IX_User_ID' is dependent on column 'User_ID'.
Msg 5074, Level 16, State 1, Line 1
The object 'FK_dbo.Notifications_dbo.Users_User_ID' is dependent on column 'User_ID'.
Msg 4922, Level 16, State 9, Line 1
ALTER TABLE DROP COLUMN User_ID failed because one or more objects access this column.

Upvotes: 4

Views: 1645

Answers (2)

Iraj
Iraj

Reputation: 1522

you can use data annonations for this :

public abstract class BaseClass
{
    [Key]
    public long ID { get; set; }

    [Required]
    public DateTime CreateDate { get; set; }

    public bool IsDeleted { get; set; }

    public BaseClass()
    {
        CreateDate = DateTime.UtcNow;
    }
}

public class Notification : BaseClass
{
    [ForeignKey("ReceiverID")]
    [InverseProperty("Receivers")]
    public User Receiver { get; set; }

    [Required, Index]
    public long ReceiverID { get; set; }


    [ForeignKey("ContextualUserID")]
    [InverseProperty("ContextualUsers")]
    public virtual User ContextualUser { get; set; }

    public long? ContextualUserID { get; set; }


    [ForeignKey("ActorID")]
    [InverseProperty("Actors")]
    public virtual User Actor { get; set; }

    public long? ActorID { get; set; }

    public string Content { get; set; }

    public string Uri { get; set; }

    [Required]
    public string Type { get; set; }

}

public class User
{
    [InverseProperty("Receiver")]
    public ICollection<Notification> Receivers { get; set; }

    [InverseProperty("ContextualUser")]
    public ICollection<Notification> ContextualUsers { get; set; }

    [InverseProperty("Actor")]
    public ICollection<Notification> Actors { get; set; }
}

for more information :

Many to many relation

Navigation property

Upvotes: 0

Can Poyrazoğlu
Can Poyrazoğlu

Reputation: 34830

It was navigation property on my User class configured incorrectly. Because Notification class didn't have a property called User but rather Receiver, and because I've forgot to add the correct name (Receiver) as an inverse property on my User class which had a Notifications collection, this extra field was generated for navigating from User to Notifications. I've added the annotation [InverseProperty("Receiver")] to my collection on User class and it now works correctly.

Upvotes: 5

Related Questions