实体框架一到零或一个没有导航属性的关系

时间:2014-02-18 11:07:29

标签: c# entity-framework code-first relationship cascading-deletes

我在尝试删除由于FK约束而导致的记录时遇到了问题。因此,我回到了绘图板,并试图说明这种关系应该如何运作。

以下是我的代码第一类:

public class MemberDataSet
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public int? DeferredDataId { get; set; }
    [ForeignKey("DeferredDataId")]
    public virtual DeferredData DeferredData { get; set; }
}

public class DeferredData
{

    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    //other properties
}

我希望实现的是MemberDataSet具有零个或一个DeferredData。我可以从MemberDataSet访问DeferredData,但DeferredData不需要导航属性返回到MemberDataSet。 DeferredData应严格要求MemberDataSet。因此,在理想的世界中,删除MemberDataSet将删除DeferredData(如果已分配)。

在我看来,我想要指明的是:

modelBuilder.Entity<MemberDataSet>().HasOptional(d => d.DeferredData).WithRequired().WillCascadeOnDelete(true);

即。 MemberDataSet有一个DeferredData选项,但DeferredData有一个必需的MemberDataSet,这个关系应该在删除时级联。

但是,我收到错误:

类型'MemberDataSet'上的属性'DeferredData'上的ForeignKeyAttribute无效。在依赖类型“DeferredData”上找不到外键名称“DeferredDataId”。 Name值应该是以逗号分隔的外键属性名称列表。

修改

在对Sam的回答感到满意之后,我继续改变了一些其他的ForeignKey属性。 MemberDataSet有另一个名为SignedOffBy的属性,它是userProfile。以前看起来像这样:

public class MemberDataSet
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public int? DeferredDataId { get; set; }
    [ForeignKey("DeferredDataId")]
    public virtual DeferredData DeferredData { get; set; }

    public int? SignedOffById { get; set; }
    [ForeignKey("SignedOffId")]
    public virtual UserProfile SignedOffBy { get; set; }
}

在下面讨论了ForeignKey属性实际上在做什么后,我将其更改为:

public class MemberDataSet
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public int? DeferredDataId { get; set; }
    [ForeignKey("Id")]
    public virtual DeferredData DeferredData { get; set; }

    public int? SignedOffById { get; set; }
    [ForeignKey("UserId")]
    public virtual UserProfile SignedOffBy { get; set; }
}

但是,我现在收到一条非常相似的错误消息:

The ForeignKeyAttribute on property 'SignedOffBy' on type 'MemberDataSet' is not valid. The foreign key name 'UserId' was not found on the dependent type 'MemberDataSet'. The Name value should be a comma separated list of foreign key property names.

这里的区别在于这种关系是多对一,即1个用户可以拥有多个签名数据集。这有什么不同?即UserProfile现在是主要对象,因此ForeignKey在MemberDataSet上?

再次感谢所有人的帮助。

1 个答案:

答案 0 :(得分:0)

错误

  

类型上属性'DeferredData'的ForeignKeyAttribute   'MemberDataSet'无效。 外键名称'DeferredDataId'   在依赖类型'DeferredData'上找不到

告诉你究竟出了什么问题。

DeferredData.Id is not DeferredData.DeferredDataId

这是你的问题。

只需删除该属性即可解决您的问题,因为Entity Framework会根据您实体的名称计算出外键。如果要保留属性,请使用:

[ForeignKey("Id")]

而不是

[ForeignKey("DeferredDataId")]

所以:

public class MemberDataSet
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public int? DeferredDataId { get; set; }
    [ForeignKey("Id")]
    public virtual DeferredData DeferredData { get; set; }
}

或将DeferredData的ID更改为DeferredDataId而不是Id

关于EF的几点说明:

  1. 名称为Id的属性自动为按键,因此无需Key属性
  2. 当您首先使用代码定义关系时,您不需要使用属性手动装饰内容,EF会根据结构进行计算。
  3. 修改

    对于一对多关系,您需要ICollection<T>

    public virtual ICollection<MemberDataSet> MemberDataSets { get; set; }
    

    UserProfile是否有UserId属性?