C# 不带外键的导航属性,或fluent api版本?

C# 不带外键的导航属性,或fluent api版本?,c#,entity-framework,ef-code-first,entity-framework-6,entity-framework-migrations,C#,Entity Framework,Ef Code First,Entity Framework 6,Entity Framework Migrations,我有一个用户表,其中一个用户可以是另一个用户的管理员(这是可选的,因此int?IdManager) 但是,当使用更新数据库时,它会中断,无法添加外键约束 但是如果我删除外键创建 public partial class manager : DbMigration { public override void Up() { AddColumn("users", "IdManager", c => c.Int()); CreateIndex("u

我有一个用户表,其中一个用户可以是另一个用户的管理员(这是可选的,因此
int?IdManager

但是,当使用
更新数据库时,它会中断,无法添加外键约束

但是如果我删除外键创建

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");
    }
}
在dbContext和Linq中一切都很好

…但是,我必须将
[ForeignKey(“Manager”)]
留在我的用户对象上(对于linq&dbcontext),这不太好,因为以后它肯定会再次在某人的脸上爆炸

关于如何通过数据属性或fluent api正确映射这一点,有什么想法吗


谢谢

我还没有测试过,但在fluent api中应该是这样的:

modelBuilder.Entity<User>()
   .HasOptional(u=>u.Manager)
   .WithMany()
   .HasForeignKey(u=>u.IdManager)
   .WillCascadeOnDelete(false);
modelBuilder.Entity()
.has可选(u=>u.Manager)
.有很多
.HasForeignKey(u=>u.IdManager)
.WillCascadeOnDelete(假);

因此,一个用户有一个可选的管理器,它可以有许多用户链接到它,而管理器没有用户集合(有许多用户没有参数),具有给定的外键属性(IdManager),并且禁用了级联删除

我尝试了另一种方法,创建了一个这样的
Employee
表并添加为一个模型,它得到了以下结果:

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);
    }
}
公共部分类员工
{
公职人员()
{
下属=新HashSet();
}
公共int Id{get;set;}
公共字符串名称{get;set;}
公共int?ManagerId{get;set;}
公共虚拟员工管理器{get;set;}
公共虚拟ICollection下属{get;set;}
}
公共类EmployeeConfiguration:EntityTypeConfiguration
{
公共雇员配置()
{
ToTable(“EmployeeDbContext”、“dbo”);
HasKey(p=>p.Id).Property(p=>p.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
属性(p=>p.Name).HasMaxLength(50);
拥有许多(p=>p.substants)。带有可选(p=>p.Manager)
.HasForeignKey(p=>p.ManagerId);
}
}

我发布的代码在引用一个表到另一个表时可以正常工作,可空只是指零或一个关系,这很好,但在引用同一个表时会中断(我遇到的问题)好人。我确信这是可行的,不幸的是,您将主键从Identity切换为None,autoincrement将不再像这样工作。它仍然生成
AddForeignKey(“用户”、“IdManager”、“用户”、“Id”)
和将
[DatabaseGeneratedOption(DatabaseGeneratedOption.None)]
添加到上面代码的主键上几乎是一样的,但不幸的是,这会抑制autoincrement handlingUpdated my code在主键上显示
[DatabaseGeneratedOption(DatabaseGeneratedOption.Identity)]
,由于这是未指定任何内容时的默认行为,我将其更改为
idenity
,并在db中手动填充了一些行。我不确定我刚才做了什么,但清理了一些迁移,确保表中的所有值都正确:Id=PK、NN、AI,然后重新运行迁移。现在它拿走了外键!您的代码实际上生成了与我的代码完全相同的带有数据注释的代码。但我会把它当作答案,因为这是一个很好的例子,用流利的API做,我很高兴你坚持,因为事情解决了!顺便说一句,和下属的接触很好。我想补充一下,因为我相信这会很有用。谢谢,非常接近!这段代码在映射过程中运行良好,但现在数据库迁移不会在数据库中生成必要的
IdManager
列。当有人试图在没有任何迁移历史记录的情况下生成整个模型,或者抛出异常,或者数据库中没有生成必要的字段时,我很担心。不是吗?它会生成什么?它会生成一个空的up()&down()…但是如果我在数据库中手动创建
IdManager
,dbcontext&linq会正常工作,这一定是因为映射的更改不需要更改db模式,但是如果您删除了迁移历史并添加了新的迁移,它将正确地创建所有内容,包括columnOk,空内容是一个bug,数据库中有一个迁移,当约束崩溃时没有恢复。现在迁移工作正常了。您的代码产生的结果实际上与我使用代码优先数据注释得到的结果完全相同。这意味着它正在尝试添加外键约束,这会导致迁移崩溃,
无法添加外键约束
:-(上面的代码实际上是有效的,迁移历史记录中有一个错误,当迁移失败时,并不是所有的更改都会恢复
modelBuilder.Entity<User>()
   .HasOptional(u=>u.Manager)
   .WithMany()
   .HasForeignKey(u=>u.IdManager)
   .WillCascadeOnDelete(false);
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);
    }
}