Navigation property without foreign key, or fluent api version?

c# ef-code-first ef-migrations entity-framework entity-framework-6

Question

I have a table of users, where a user can be the manager of another user (this is optional, thus int? IdManager)

[Table("users")]
public partial class User
{
    #region Properties
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Key]
    [Required]
    [Column("Id")]
    public int Id { get; set; }
    #endregion

    #region DataNavigation
    /// <summary>
    /// Navigation Id for getting parent Field
    /// WARNING: this works, but need to remove foreign key creation in migration file !
    /// </summary>
    [ForeignKey("Manager")]
    [Column("IdManager")]
    public int? IdManager { get; set; }

    /// <summary>
    /// Navigation object to parent Field
    /// </summary>
    [ScriptIgnore]
    [JsonIgnore]
    [IgnoreDataMember]
    public virtual User Manager { get; set; }
    #endregion
}

Now in code first, the above code generates this

public partial class manager : DbMigration
{
    public override void Up()
    {
        AddColumn("users", "IdManager", c => c.Int());
        CreateIndex("users", "IdManager");
        AddForeignKey("users", "IdManager", "users", "Id");
    }

    public override void Down()
    {
        DropForeignKey("users", "IdManager", "users");
        DropIndex("users", new[] { "IdManager" });
        DropColumn("users", "IdManager");
    }
}

However it breaks while updating the database with Cannot add foreign key constraint

But if i delete the foreign key creation

public partial class manager : DbMigration
{
    public override void Up()
    {
        AddColumn("users", "IdManager", c => c.Int());
        CreateIndex("users", "IdManager");
    }

    public override void Down()
    {
        DropIndex("users", new[] { "IdManager" });
        DropColumn("users", "IdManager");
    }
}

Everything works fine in dbContext and Linq

...but, i have to leave [ForeignKey("Manager")] on my user object (for linq & dbcontext), which is not so good, since at a later time it will certainly blow up in someones face again.

Any idea on how i can map this properly either via Data Attributes or fluent api ?

Thanks!

1
1
11/7/2015 7:45:03 PM

Accepted Answer

I tried the other way, created one such Employee table and added as a model, it got me this:

public partial class Employee
{
    public Employee()
    {
        Subordinates = new HashSet<Employee>();
    }
    public int Id { get; set; }
    public string Name { get; set; }
    public int? ManagerId { get; set; }
    public virtual Employee Manager { get; set; }
    public virtual ICollection<Employee> Subordinates { get; set; }
}

public class EmployeeConfiguration: EntityTypeConfiguration<Employee>
{
    public EmployeeConfiguration()
    {
        ToTable("EmployeeDbContext", "dbo");
        HasKey(p => p.Id).Property(p => p.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        Property(p => p.Name).HasMaxLength(50);
        HasMany(p => p.Subordinates).WithOptional(p => p.Manager)
                                 .HasForeignKey(p => p.ManagerId);
    }
}
0
11/7/2015 7:52:33 PM

Popular Answer

I haven't tested it, but in fluent api it should be like this:

modelBuilder.Entity<User>()
   .HasOptional(u=>u.Manager)
   .WithMany()
   .HasForeignKey(u=>u.IdManager)
   .WillCascadeOnDelete(false);

So, a User has an optional Manager, which can have many users linking to it without the Manager having a collection of Users (WithMany without parameters), with the given foreign key property (IdManager) and with cascade delete disabled.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow