C# 实体框架5代码优先自引用关系

C# 实体框架5代码优先自引用关系,c#,entity-framework,foreign-keys,entity-framework-5,C#,Entity Framework,Foreign Keys,Entity Framework 5,如何在EntityFramework5中映射以下关系 public class Item { public int Id { get; set; } public int? ParentItemId { get; set; } public string Value { get; set; } public Item ParentItem { get; set; } public List<Item> ChildItems { get; set; } } 公共

如何在EntityFramework5中映射以下关系

public class Item {
  public int Id { get; set; }
  public int? ParentItemId { get; set; }
  public string Value { get; set; }

  public Item ParentItem { get; set; }
  public List<Item> ChildItems { get; set; }
}
公共类项目{
公共int Id{get;set;}
public int?ParentItemId{get;set;}
公共字符串值{get;set;}
公共项ParentItem{get;set;}
公共列表子项{get;set;}
}
我试过这个:

protected override void OnModelCreating(DbModelBuilder modelBuilder) {
  base.OnModelCreating(modelBuilder);

  modelBuilder.Entity<Item>()
              .HasOptional(i => i.ParentItem)
              .WithMany(i => i.ChildItems)
              .HasForeignKey(i => i.ParentItemId);
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder){
基于模型创建(modelBuilder);
modelBuilder.Entity()
.has可选(i=>i.ParentItem)
.WithMany(i=>i.ChildItems)
.HasForeignKey(i=>i.ParentItemId);
}
这是:

protected override void OnModelCreating(DbModelBuilder modelBuilder) {
  base.OnModelCreating(modelBuilder);

  modelBuilder.Entity<Item>()
              .HasMany(i => i.ChildItems)
              .WithOptional(i => i.ParentItem)
              .HasForeignKey(i => i.ParentItemId);
}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder){
基于模型创建(modelBuilder);
modelBuilder.Entity()
.HasMany(i=>i.ChildItems)
.WithOptional(i=>i.ParentItem)
.HasForeignKey(i=>i.ParentItemId);
}
这两者都会导致此错误:

引用约束的从属角色中所有属性的类型必须与主体角色中相应的属性类型相同。

如果从数据库优先映射开始,则生成的实体如下所示:

public partial class Item
{
    public Item()
    {
        this.ChildItems = new HashSet<Item>();
    }

    public int Id { get; set; }
    public Nullable<int> ParentItemId { get; set; }
    public string Value { get; set; }

    public virtual ICollection<Item> ChildItems { get; set; }
    public virtual Item ParentItem { get; set; }
}
公共部分类项
{
公共项目()
{
this.ChildItems=new HashSet();
}
公共int Id{get;set;}
公共可为空的ParentItemId{get;set;}
公共字符串值{get;set;}
公共虚拟ICollection子项{get;set;}
公共虚拟项ParentItem{get;set;}
}

我知道如果我先从db开始,这会起作用,我只需要知道如何首先在代码中定义关系。

尝试使用mapKey方法,而不是使用HasForeignKey。像

modelBuilder.Entity<Course>()
    .HasRequired(c => c.Department)
    .WithMany(t => t.Courses)
    .Map(m => m.MapKey("ChangedDepartmentID"));
modelBuilder.Entity()
.HasRequired(c=>c.Department)
.有许多(t=>t.课程)
.Map(m=>m.MapKey(“ChangedDepartmentID”);

在代码中,首先更改实体类,如下所示:

   public class Item 
   {
      public Item()
      {
            this.ChildItems = new HashSet<Item>();
      }

      public int Id { get; set; }
      public Nullable<int> ParentItemId { get; set; }
      public string Value { get; set; }

      public virtual Item ParentItem { get; set; }
      public virtual ICollection<Item> ChildItems { get; set; }
  }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Item>()
                    .HasOptional(i => i.ParentItem)
                    .WithMany(i => i.ChildItems)
                    .HasForeignKey(i => i.ParentItemId);
    }
公共类项目
{
公共项目()
{
this.ChildItems=new HashSet();
}
公共int Id{get;set;}
公共可为空的ParentItemId{get;set;}
公共字符串值{get;set;}
公共虚拟项ParentItem{get;set;}
公共虚拟ICollection子项{get;set;}
}
将以下代码写入上下文文件:

   public class Item 
   {
      public Item()
      {
            this.ChildItems = new HashSet<Item>();
      }

      public int Id { get; set; }
      public Nullable<int> ParentItemId { get; set; }
      public string Value { get; set; }

      public virtual Item ParentItem { get; set; }
      public virtual ICollection<Item> ChildItems { get; set; }
  }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Item>()
                    .HasOptional(i => i.ParentItem)
                    .WithMany(i => i.ChildItems)
                    .HasForeignKey(i => i.ParentItemId);
    }
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity()
.has可选(i=>i.ParentItem)
.WithMany(i=>i.ChildItems)
.HasForeignKey(i=>i.ParentItemId);
}

我想这应该行得通。

例外意味着:

  • “从属角色中所有属性的类型”是FK属性的类型,它是
    ParentItemId
    ,并且在您的模型中具有类型
    int?
  • “主体角色中的对应属性类型”是PK属性的类型,它是
    Id
    ,并且在您的模型中具有类型
    int
它们是相同的(可空性并不重要)。然而,例外情况是,他们不是

通常,只有当类型不匹配时才会发生异常,例如,如果PK有
long
(或任何其他类型),而FK有
int?

为什么不尝试以下方法:

 public class Item 
   {
      public Item()
      {
            ChildItems = new HashSet<Item>();
      }

      public int Id { get; set; }
      public int? ParentItemId { get; set; }
      public string Value { get; set; }

      public virtual Item ParentItem { get; set; }
      public virtual ICollection<Item> ChildItems { get; set; }
  }
公共类项目
{
公共项目()
{
ChildItems=新HashSet();
}
公共int Id{get;set;}
public int?ParentItemId{get;set;}
公共字符串值{get;set;}
公共虚拟项ParentItem{get;set;}
公共虚拟ICollection子项{get;set;}
}
在DataContex类中:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Item>()
                    .HasOptional(i => i.ParentItem)
                    .WithMany()
                    .HasForeignKey(i => i.ParentItemId);
    }
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Entity()
.has可选(i=>i.ParentItem)
.有很多
.HasForeignKey(i=>i.ParentItemId);
}
希望这能奏效

这里还有一篇好文章: 如何首先在代码中配置自引用实体

Id是密钥属性吗?或者您是否有一个键映射(使用Fluent API?)到另一个属性,例如到
Value
?Id是项的主键属性。“依赖角色中所有属性的类型”是指FK属性的类型,它是
ParentItemId
,并且具有类型
int?
。“主体角色中的对应属性类型”是指PK属性的类型,该属性为
Id
,类型为
int
。它们是相同的(可空性并不重要)。然而,例外情况是,他们不是。例如,如果PK使用
long
(或任何其他类型),FK使用
int?
,则会发生异常。很奇怪…我复制了你发布的代码并运行了它,它在我的系统上运行时没有错误。我可以创建和读取项目,不会引发异常。我正在使用VS2013 RC和EF6@Slauma这就是问题所在。我在这里发布了一个问题的简化表示(因为真正的实体是巨大的),但该项的主键实际上被标记为long。谢谢你指出这一点。请发布一个回复,我会将其标记为答案。感谢您抽出时间回答。当尝试这种方式时,我仍然会得到相同的错误:引用约束的从属角色中所有属性的类型必须与主体角色中相应的属性类型相同。感谢您花时间回答。当以这种方式尝试时,我得到以下错误:类型中的每个属性名称必须是唯一的。已定义属性名称“ParentItemId”。请在上述多对一映射之前添加对ParentItemId属性权限的忽略。。modelBuilder.Entity().Ignore(it=>it.ParentItemId);