Reputation: 2416
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!
Upvotes: 1
Views: 7730
Reputation: 1495
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);
}
}
Upvotes: 0
Reputation: 2857
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.
Upvotes: 4