繁体   English   中英

是否可以在没有外键的情况下设置导航属性?

[英]Is it possible to set up a navigation property without the foreign key?

是否可以有两个(或多个)相同类型的导航属性?

我的模型看起来像这样......

public class Agreement
{
    public int Id { get; set; }
    public Guid? BuyerId { get; set; }
    public Guid? SellerId { get; set; }

    public AgreementInfo ByerAgreementInfo { get; set; }
    public AgreementInfo SellerAgreementInfo { get; set; }
}

public class AgreementInfo
{
    // PK is AgreementId and OwnerActorId combined.
    public int AgreementId { get; set; }
    public Guid OwnerActorId { get; set; }
    public string Name { get; set; }
}

...我试图通过匹配AgreementId和ByerId/SellerId来包含导航属性...

modelBuilder.Entity<Agreement>().HasOne(x => x.ByerAgreementInfo).WithOne().HasForeignKey<Agreement>(x => new {x.Id, x.ProviderId});
modelBuilder.Entity<Agreement>().HasOne(x => x.SellerAgreementInfo).WithOne().HasForeignKey<Agreement>(x => new { x.Id, x.RequesterId });

...但这会导致循环依赖。

有没有办法在不使用外键的情况下包含这些属性? 或者是否有另一种解决方案(除了向信息表添加一个 id 列)允许我使用信息表行作为协议类中的导航属性?

有很多方法可以实现您想要的。 您可以在您的子项上使用具有InverseProperty属性的数据注释,在您的父项上使用ForeignKey属性,或者在模型构建器中以任何一种方式使用流畅的语法 我倾向于尽可能使用属性(数据注释)(这只是我个人的喜好),我发现它需要查看实际模式本身中的关系(尽管其他人可能不会)。

使用ForeignKey属性:

public class Agreement
{
    ...

    [ForeignKey("ByerAgreementInfo ")]
    public int ByerAgreementInfoId { get; set; }
    public AgreementInfo ByerAgreementInfo { get; set; }

    [ForeignKey("SellerAgreementInfo ")]
    public int SellerAgreementInfoId { get; set; }
    public AgreementInfo SellerAgreementInfo { get; set; 
}

使用InverseProperty属性:

public class AgreementInfo
{

    ...

    [InverseProperty("ByerAgreementInfo ")]
    public ICollection<Agreement> Sellers { get; set; }
    [InverseProperty("SellerAgreementInfo ")]
    public ICollection<Agreement> Buyers { get; set; }
}

如果您想使用Fluent Syntax ,我相信以下方法会起作用(尽管我已经有一段时间没有使用它了):

modelBuilder.Entity<Agreement>()
    .HasOne(x => x.ByerAgreementInfo)
    .WithOne()
    .HasForeignKey<Agreement>(p => p.ByerAgreementInfoId);

modelBuilder.Entity<Agreement>()
    .HasOne(x => x.SellerAgreementInfo)
    .WithOne()
    .HasForeignKey<Agreement>(p => p.SellerAgreementInfoId);

注意:我认为您可能需要模型中的实际 Id,但我不记得了。

...但这会导致循环依赖

是的! 它会。 要克服这个问题,您必须指定.OnDelete(DeleteBehavior.Restrict); 在您的Fluent API配置中,如下所示,但首先您也必须按如下方式编写您的Agreement模型类:

public class Agreement
{
    public int Id { get; set; }
    public Guid? BuyerId { get; set; }
    public Guid? SellerId { get; set; }

    public int AgreementIdForBuyer { get; set; }
    public Guid OwnerActorIdForBuyer { get; set; }

    public int AgreementIdForSeller { get; set; }
    public Guid OwnerActorIdForSeller { get; set; }

    public AgreementInfo ByerAgreementInfo { get; set; }
    public AgreementInfo SellerAgreementInfo { get; set; }
}

现在在Fluent API配置中:

modelBuilder.Entity<Agreement>()
    .HasOne(x => x.ByerAgreementInfo)
    .WithOne()
    .HasForeignKey<Agreement>(p => new {p.AgreementIdForBuyer, p.AgreementIdForBuyer})
    .OnDelete(DeleteBehavior.Restrict); // <-- Here it is

modelBuilder.Entity<Agreement>()
    .HasOne(x => x.SellerAgreementInfo)
    .WithOne()
    .HasForeignKey<Agreement>(p => new {p.AgreementIdForSeller, p.OwnerActorIdForSeller})
    .OnDelete(DeleteBehavior.Restrict); // <-- Here it is

暂无
暂无

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

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