简体   繁体   English

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

[英]Entity framework one to zero or one relationship without navigation property

I hit an issue when trying to delete records due to FK constraints. 由于FK限制,在尝试删除记录时遇到问题。 I therefore went back to the drawing board and am trying to specify how the relationship should work. 因此,我回到了绘图板上,试图指定这种关系应该如何工作。

Here are my code first classes: 这是我的代码头等舱:

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
}

What I am looking to achieve is that the MemberDataSet has zero or one DeferredData. 我希望实现的是MemberDataSet具有零或一个DeferredData。 I can access DeferredData from MemberDataSet but DeferredData does not need a navigation property back to MemberDataSet. 我可以从MemberDataSet访问DeferredData,但DeferredData不需要导航属性回到MemberDataSet。 DeferredData should strictly require a MemberDataSet. DeferredData应该严格要求使用MemberDataSet。 In an ideal world deleting MemberDataSet will therefore delete DeferredData if assigned. 在理想情况下,删除MemberDataSet会因此删除DeferredData(如果已分配)。

What seemed to me to be what I wanted to specify is this: 在我看来,我想指定的是:

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

ie MemberDataSet has an option DeferredData but DeferredData has a required MemberDataSet and this relationship should cascade on delete. 即MemberDataSet有一个选项DeferredData但DeferredData有一个必需的MemberDataSet,并且此关系在删除时应该级联。

However, I then get an error: 但是,我得到一个错误:

The ForeignKeyAttribute on property 'DeferredData' on type 'MemberDataSet' is not valid. 类型'MemberDataSet'上属性'DeferredData'的ForeignKeyAttribute无效。 The foreign key name 'DeferredDataId' was not found on the dependent type 'DeferredData'. 在从属类型“ DeferredData”上找不到外键名称“ DeferredDataId”。 The Name value should be a comma separated list of foreign key property names. Name值应该是逗号分隔的外键属性名称列表。

Edit 编辑

After feeling happy with Sam's answer below I went ahead and changed a few other ForeignKey attributes. 在对下面的Sam回答感到满意之后,我继续进行并更改了其他一些ForeignKey属性。 MemberDataSet has another property called SignedOffBy that is a userProfile. MemberDataSet具有另一个名为SignedOffBy的属性,它是一个UserProfile。 This previously looked like this: 以前看起来像这样:

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; }
}

After discussion below on what ForeignKey attribute is actually doing I changed this to: 在下面讨论了什么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; }
}

However, I now get a very similar error message: 但是,我现在收到非常相似的错误消息:

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.

The difference here is that this relationship is Many to One ie 1 user can have several signedoff datasets. 此处的区别在于,这种关系是多对一关系,即1个用户可以有多个签名数据集。 Is this what makes the difference? 这有什么区别吗? ie the UserProfile is now the principal object so the ForeignKey is on the MemberDataSet? 即UserProfile现在是主要对象,因此ForeignKey在MemberDataSet上吗?

Many thanks again for any and all help. 再次非常感谢您提供的所有帮助。

The error 错误

The ForeignKeyAttribute on property 'DeferredData' on type 'MemberDataSet' is not valid. 类型'MemberDataSet'上属性'DeferredData'的ForeignKeyAttribute无效。 The foreign key name 'DeferredDataId' was not found on the dependent type 'DeferredData'. 在从属类型“ DeferredData”上找不到外键名称 “ DeferredDataId”。

is telling you exactly what is wrong. 告诉你到底是什么问题。

DeferredData.Id is not DeferredData.DeferredDataId

This is your problem. 这是你的问题。

Just removing the attribute will solve your problem as Entity Framework figures out foreign keys based on the name of your entities. 只需删除属性即可解决您的问题,因为Entity Framework根据您的实体名称确定外键。 If you want to keep the attributes, use: 如果要保留属性,请使用:

[ForeignKey("Id")]

instead of 代替

[ForeignKey("DeferredDataId")]

So: 所以:

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; }
}

or change the Id of DeferredData to be DeferredDataId and not Id 或将DeferredData的ID更改为DeferredDataId而不是Id

A few notes about EF: 关于EF的一些注意事项:

  1. Properties with names Id are automatically Keys, so no need for the Key attribute 名称为Id属性自动为键,因此不需要Key属性
  2. When you define a relationship using code first you don't need to manually decorate things with attributes, EF figures it out based on the structure. 当您首先使用代码定义关系时,您无需手动使用属性来装饰事物,EF会根据结构进行计算。

Edit: 编辑:

For a One-to-many relationship you need an ICollection<T> 对于一对多关系,您需要ICollection<T>

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

Does UserProfile have a UserId property? UserProfile是否具有UserId属性?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM