.net 具有两端可选和两个FK的一对一可选关系

.net 具有两端可选和两个FK的一对一可选关系,.net,entity-framework,ef-code-first,entity-framework-6,.net,Entity Framework,Ef Code First,Entity Framework 6,我在回答这个问题: 我的关系建立如下: public class Review { [Key] public int ReviewId { get; set; } public virtual Payment Payment { get; set; } } public class Payment { [Key] public int PaymentId { get; set; } [ForeignKey("Review")] pub

我在回答这个问题:

我的关系建立如下:

public class Review {
    [Key]
    public int ReviewId { get; set; }

    public virtual Payment Payment { get; set; }
}

public class Payment {
    [Key]
    public int PaymentId { get; set; }

    [ForeignKey("Review")]
    public int? ReviewId { get; set; }
    public virtual Review Review { get; set; }
}

    public class ReviewConfiguration : EntityTypeConfiguration<Review>
{
    public ReviewConfiguration()
    {
        // One-to-One Optional
        HasOptional<Payment>(s => s.Payment).WithOptionalDependent(s => s.Review).Map(s => s.MapKey("PaymentId"));
    }
}
公共课复习{
[关键]
public int ReviewId{get;set;}
公共虚拟支付{get;set;}
}
公共类支付{
[关键]
public int PaymentId{get;set;}
[外键(“审查”)]
公共int?ReviewId{get;set;}
公共虚拟审阅{get;set;}
}
公共类审阅配置:EntityTypeConfiguration
{
公开评论配置()
{
//一对一可选
has可选(s=>s.Payment).with可选依赖(s=>s.Review).Map(s=>s.MapKey(“PaymentId”);
}
}
我得到一个有效的关键点,但另一个从来没有映射为可选的FK:

我做错了什么

我见过一些奇怪的黑客解决方案,包括创建空列表等等——这不是我想要的。我正在寻找一个合适的方法-它必须存在。。。对吧?

更新


我现在正在使用上面的方法-当我手头有付款并且需要访问或删除评论时,我必须在[pseudo FK]ReviewId上进行另一次查找,这太糟糕了

您的模型中必须有打字错误(付款中有2个ReviewId字段?)。此外,如果你要走流畅的路线,不要在那里放任何关系属性来混淆问题。IAC,试试这样:

public class Review {
    public int ReviewId { get; set; }

    public int? PaymentId { get; set; }
    public virtual Payment Payment { get; set; }
}

public class Payment {
    public int PaymentId { get; set; }

    public int? ReviewId { get; set; }
    public virtual Review Review { get; set; }
}

public class ReviewConfiguration : EntityTypeConfiguration<Review>
{
    public ReviewConfiguration()
    {
        HasOptional(r => r.Payment)
            .WithMany()
            .HasForeignKey(r => r.PaymentId);
    }
}

public class PaymentConfiguration : EntityTypeConfiguration<Payment>
{
    public PaymentConfiguration()
    {
        HasOptional(p => p.Review)
            .WithMany()
            .HasForeignKey(p => p.ReviewId);
    }
}
公共课复习{
public int ReviewId{get;set;}
public int?PaymentId{get;set;}
公共虚拟支付{get;set;}
}
公共类支付{
public int PaymentId{get;set;}
公共int?ReviewId{get;set;}
公共虚拟审阅{get;set;}
}
公共类审阅配置:EntityTypeConfiguration
{
公开评论配置()
{
HAS可选(r=>r.Payment)
.有很多
.HasForeignKey(r=>r.PaymentId);
}
}
公共类PaymentConfiguration:EntityTypeConfiguration
{
公共支付配置()
{
HAS可选(p=>p.Review)
.有很多
.HasForeignKey(p=>p.ReviewId);
}
}

在任何一对一关联中,EF只使用一个外键。如前所述,当需要关联时,外键也将是从属实体的主键

当关联是可选的时,两个实体应该能够独立存在。所以它们的主键不能是外键,因为PKs不能是可选的。这里需要一个附加的可空FK字段来建立可选关联

在您的情况下,从技术上讲,哪个实体具有FK字段并不重要(从逻辑上讲,它可能)。我用过这个模型:

public class Review
{
    [Key]
    public int ReviewId { get; set; }
    public virtual Payment Payment { get; set; }
}

public class Payment
{
    [Key]
    public int PaymentId { get; set; }

    public Review Review { get; set; }
}
使用此映射:

public class ReviewConfiguration : EntityTypeConfiguration<Review>
{
    public ReviewConfiguration()
    {
        // One-to-One Optional
        HasOptional(s => s.Payment)
            .WithOptionalDependent(s => s.Review)
            .Map(s => s.MapKey("PaymentId"));
    }
}
。。。其中
db
当然是一个上下文。两个表的内容现在都是:

PaymentId
-----------
1
2

ReviewId    PaymentId
----------- -----------
1           1
2           2
我可以像这样双向查询数据:

var data = db.Set<Review>().Include(r => r.Payment).ToList();

现在,在表
付款
中会有一个FK字段
ReviewId
,其余代码可以正常工作。

谢谢。我在复制/粘贴-更正的过程中破坏了我的模型。我会试试这个,然后发回结果。谢谢Steve。我在这里得到以下信息:PaymentId:Name:类型中的每个属性名称都必须是唯一的。已定义属性名称“PaymentId”。ReviewId:Name:类型中的每个属性名称都必须是唯一的。属性名“ReviewId”已经定义。我尝试过对这里的内容进行多次修改,但都没有效果。投票不准确,但如果我们找到一些有效的方法,我们会纠正的。对不起,这是我的想法。我查了一下我的代码,它实际上是上面的样子。您必须使用WithMany()或使主键成为我不喜欢的外键。我只是在我这边测试了一下,它对我有效。这不起作用。这与我的上述困境正好相反——就好像那些盒子被交换了一样。这不可能是你的模型+映射。它给出了一个错误:在类型“Payment”上声明的导航属性“Review”已配置有冲突的外键。@GertArnold我就是这样配置的。只是双重和三重检查。您是否有正在审核的PaymentId?我不。顺便说一下,谢谢你尝试一下。非常令人沮丧的东西,奇怪。无论如何EF不需要FK审查。有了一个可选的FK PaymentId,它就知道有足够的信息来建立双向关联。@GertArnold我目前的困境向我展示了另一种情况。我仍然无法在两个实体之间配置完全双向的互选关系。为了确保我们在同一页上:我只从模型中删除了
ReviewId
,而不是
Review
(属性)。非常感谢。我唯一关心的是,db.SaveChanges()实际上并没有填充另一端的可为空的非主FK,但我需要再次进行测试。别担心,它确实存在。EF首先保存主体实体,然后使用其生成的PK值在从属实体中设置FK字段,所有都在封面下(当然是一次交易)。再次感谢各位。我知道这需要一些时间。
var data = db.Set<Review>().Include(r => r.Payment).ToList();
var data = db.Set<Payment>().Include(r => r.Review).ToList();
public class PaymentConfiguration : EntityTypeConfiguration<Payment>
{
    public PaymentConfiguration()
    {
        // One-to-One Optional
        HasOptional(s => s.Review)
            .WithOptionalDependent(s => s.Payment)
            .Map(s => s.MapKey("ReviewId"));
    }
}