【问题标题】:Entity framework one to zero or one relationship without navigation property实体框架一对零或一对无导航属性的关系
【发布时间】:2014-03-18 02:17:22
【问题描述】:

由于 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 上?

再次感谢您的任何帮助。

【问题讨论】:

  • 您不需要ForeignKey 属性。 EF 从名称中推断出来。
  • 是的,但它不会推断出我指定的内容吗?

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


【解决方案1】:

错误

类型上属性“DeferredData”的 ForeignKeyAttribute “成员数据集”无效。 外键名称“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 会根据结构计算出来。

编辑:

对于一对多关系,您需要ICollection&lt;T&gt;

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

UserProfile 是否有 UserId 属性?

【讨论】:

  • 谢谢。我可以在这里看到一些逻辑,但仍然有些困惑。我原以为属性 [ForeignKey("DeferredDataId")] 告诉它我的导航属性的 ForeignKey 是 MemberDataSet 的 DeferredDataId 属性。不对吗?
  • 不,通过使用该属性,您在声明 DeferredData 中要用作 MemberDataSet 中的外键的键称为 DeferredDataId。不叫DeferredDataId,就叫Id
  • 好的,这开始有意义了。那么public int有什么意义呢? DeferredDataId { 获取;放; }?即可以删除吗?是自动接线的吗?等
  • 哈!我确实可以。我认为它是必需的,因为我见过的所有示例似乎都有一个。因此,我认为它必须具有自动附加的 NavPropertyNameId 格式。或者你能称之为不同的东西吗?如果是这样,你会如何告诉它它叫什么?我曾认为(错误地,正如您在上面所阐述的那样)这就是 FK 属性的用途(因此是装饰!顺便说一句,我也很喜欢添加特定属性,所以我很清楚自己在做什么)跨度>
  • 在阅读了许多页面之后,我仍然不知道如何回答这个问题:“因此,我认为它必须具有 NavPropertyNameId 格式才能自动附加。或者你可以称之为不同的东西吗?如果是这样你怎么告诉它叫什么?”感谢您的帮助。
猜你喜欢
  • 2015-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多