问题描述
由于FK限制,在尝试删除记录时遇到问题。因此,我回到了绘图板上,试图指定这种关系应该如何工作。
I hit an issue when trying to delete records due to FK constraints. I therefore went back to the drawing board and am trying to specify how the relationship should work.
这是我的第一类代码:
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。
What I am looking to achieve is that the MemberDataSet has zero or one DeferredData. I can access DeferredData from MemberDataSet but DeferredData does not need a navigation property back to MemberDataSet. DeferredData should strictly require a MemberDataSet. In an ideal world deleting MemberDataSet will therefore delete DeferredData if assigned.
在我看来,我想指定的是:
What seemed to me to be what I wanted to specify is this:
modelBuilder.Entity<MemberDataSet>().HasOptional(d => d.DeferredData).WithRequired().WillCascadeOnDelete(true);
即MemberDataSet有一个选项DeferredData但DeferredData有一个必需的MemberDataSet,并且此关系应该在删除时级联。
i.e. MemberDataSet has an option DeferredData but DeferredData has a required MemberDataSet and this relationship should cascade on delete.
但是,然后我得到一个错误:
However, I then get an error:
类型'MemberDataSet'上属性'DeferredData'的ForeignKeyAttribute无效。在依赖类型 DeferredData上找不到外键名称 DeferredDataId。名称值应该是用逗号分隔的外键属性名称列表。
The ForeignKeyAttribute on property 'DeferredData' on type 'MemberDataSet' is not valid. The foreign key name 'DeferredDataId' was not found on the dependent type 'DeferredData'. The Name value should be a comma separated list of foreign key property names.
编辑
对下面的Sam回答感到满意之后,我继续进行了更改,并更改了其他一些ForeignKey属性。 MemberDataSet具有另一个名为SignedOffBy的属性,它是一个UserProfile。以前看起来是这样的:
After feeling happy with Sam's answer below I went ahead and changed a few other ForeignKey attributes. MemberDataSet has another property called SignedOffBy that is a 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; }
}
在下面讨论了ForeignKey属性的作用之后,我将其更改为:
After discussion below on what ForeignKey attribute is actually doing I changed this to:
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.
这里的区别是这种关系是多对一的,即1个用户可以有多个签名数据集。这有什么区别吗?即UserProfile现在是主要对象,因此ForeignKey在MemberDataSet上吗?
The difference here is that this relationship is Many to One i.e. 1 user can have several signedoff datasets. Is this what makes the difference? i.e. the UserProfile is now the principal object so the ForeignKey is on the MemberDataSet?
再次感谢您提供的所有帮助。
Many thanks again for any and all help.
推荐答案
错误
告诉您确切的问题是什么。
is telling you exactly what is wrong.
DeferredData.Id is not DeferredData.DeferredDataId
这是您的问题。
只需删除该属性即可解决您的问题,因为实体框架根据您的实体名称找出外键。如果要保留属性,请使用:
Just removing the attribute will solve your problem as Entity Framework figures out foreign keys based on the name of your entities. If you want to keep the attributes, use:
[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 c $ c>为
DeferredDataId
而不是 Id
有关EF的一些注意事项:
A few notes about EF:
- 名称为
Id
的属性是自动键,因此不需要Key
属性 - 使用代码定义关系时,您无需手动装饰属性,EF会根据结构进行计算。
- Properties with names
Id
are automatically Keys, so no need for theKey
attribute - 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.
编辑:
对于一对多关系,您需要 ICollection< T>
For a One-to-many relationship you need an ICollection<T>
public virtual ICollection<MemberDataSet> MemberDataSets { get; set; }
UserProfile
是否具有 UserId
属性?
这篇关于没有导航属性的实体框架一对零或一种关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!