在实体框架代码中首先了解ForeignKey属性 [英] Understanding ForeignKey attribute in entity framework code first

查看:125
本文介绍了在实体框架代码中首先了解ForeignKey属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

查看以下帖子的一些背景:



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



我一直以为 ForeignKey 用于显示一个类中的哪个属性持有确定导航属性的ForeignKey,例如

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

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

然而,我发现在链接的帖子这是不对的,因为DeferredData的主键被称为Id我实际需要:

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

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

ForeignKey 用于指向另一个类。



然后我继续更改其他一些参考: / p>

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

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

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

但是,这失败了。在此之前,将 ForeignKey 需要指向 MemberDataSet 类的Id。

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

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

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

我认为这是因为这个第二个关系是一对多,而第一个是一个零到一个,有效的关系的主要结局是不同的,但我会很清楚这一点/提到好的文章,所以我可以理解发生了什么,究竟外国人正在做什么。



我还在上面的例子中寻找清楚如何 public int? DeferredDataId {get;组;因为它没有明确地链接到 DeferredData 。我很高兴这将按照惯例来匹配,但是我如何明确地告诉它,例如如果它有不同的名字?我在这个关于使用 ForeignKey 属性的例子中看到的例子,但这不能是上述所有情况下的答案!



所有帮助非常感谢 - 寻求理解这个问题,而不是解决一个特定的问题,因为我在模型中有很多参考,所以需要确定每个方法。



谢谢。



修改



添加其他类帮助:

  public class DeferredData 
{

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

//其他属性
}

public class UserProfile
{

[Key]
[ DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId {get;组; }

//其他属性
}


解决方案

1..0关系 MemberDataSet 所需的一侧不应该有一个FK到 DeferredData 。相反, DeferredData 的PK也应该是一个FK到 MemberDataSet (称为共享主键)

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

public virtual DeferredData DeferredData {get;组; }
}

public class DeferredData
{
// DeferredData.Id既是PK和一个FK到MemberDataSet
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
[ForeignKey(MemberDataSet)]
public int Id {get;组;

[必需]
public virtual MemberDataSet MemberDataSet {get;组;
}

流利的API:



$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ b $ );


See the following post for some background:

Entity framework one to zero or one relationship without navigation property

I had always thought that ForeignKey was used to show which property in a class held the ForeignKey that determined the navigation property e.g.

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

However, I discovered on the linked post that this is not right and that as DeferredData's primary key was called Id I actually needed:

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

i.e. ForeignKey is used to point to the other class.

I then proceeded to change some of the other references:

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, this failed. Turned out on this one the ForeignKey needed to point to the Id on MemberDataSet class.

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("SignedOffById")]
    public virtual UserProfile SignedOffBy { get; set; }
}

I presume this is because this second relationship is one to many whereas the first was one to zero or one, and that effectively the principal end of the relationship differs, but I would appreciate some clarity on this/references to good articles, so I can understand what is happening and exactly what ForeignKey is doing.

I was also looking for clarity in the example above of how public int? DeferredDataId { get; set; } fits into the equation given it is not explicitly linked to DeferredData. I am happy this will match up by convention but how would I explicitly tell it this e.g. if it had a different name? Al the examples I have seen on this talk about using the ForeignKey attribute but this can't be the answer in all cases per above!

All help greatly appreciated - looking to understand the issue rather than fix a specific problem as I have lots of references in my model so need to establish what approach to take with each.

Thanks.

Edit

Added other classes to help:

public class DeferredData
{

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

    //other properties
}

public class UserProfile
{

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

    //other properties
}

解决方案

The required side of the 1..0 relationship MemberDataSet should not have a FK to DeferredData. Instead, DeferredData's PK should also be a FK to MemberDataSet (known as shared primary key)

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

    public virtual DeferredData DeferredData { get; set; }
}

public class DeferredData
{
    // DeferredData.Id is both the PK and a FK to MemberDataSet
    [Key]
    [DatabaseGenerated( DatabaseGeneratedOption.None )]
    [ForeignKey( "MemberDataSet" )]
    public int Id { get; set; }

    [Required]
    public virtual MemberDataSet MemberDataSet { get; set; }
}

Fluent API:

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

这篇关于在实体框架代码中首先了解ForeignKey属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆