简体   繁体   English

一对一可选关系,两端可选,两个FK

[英]One-to-One optional relationship with both ends optional and both FKs

I'm following this question: EF Code First - 1-to-1 Optional Relationship 我正在关注这个问题: EF Code First - 1对1可选关系

And I have my relationships set up as follows: 我的关系设置如下:

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

And I get ONE of the keys valid, but the other is never mapped as an optional FK: 我得到一个有效的密钥,但另一个从未映射为可选的FK:

在此输入图像描述

What am I doing wrong? 我究竟做错了什么?

I've seen some weird hacky solutions involving creating empty Lists etc - not what I'm looking for. 我已经看到一些奇怪的hacky解决方案涉及创建空列表等 - 而不是我正在寻找的。 I'm looking for a proper approach here - it has to exist... right? 我在这里寻找一个合适的方法 - 它必须存在......对吗?

Update 更新

I'm using the above now - when I have the Payment on hand and need to access or delete the Review, I have to do another lookup on the [pseudo-FK] ReviewId, which totally sucks. 我现在正在使用上面的内容 - 当我手头有付款并且需要访问或删除评论时,我必须在[伪FK] ReviewId上进行另一次查找,这完全很糟糕。

In any one-to-one association, EF uses only one foreign key. 在任何一对一关联中,EF仅使用一个外键。 When the association is required, the foreign key will also be the primary key of the dependent entity, as explained here . 当需要的关联,外键也将取决于实体的主键,如解释在这里

When the association is optional, both entities should be able to exist independent of one another. 当关联是可选的时,两个实体应该能够彼此独立地存在。 So their primary keys can't be foreign keys, because PKs can't be optional. 所以他们的主键不能是外键,因为PK不能是可选的。 Here an additional nullable FK field is required to establish the optional association. 这里需要一个额外的可空FK字段来建立可选的关联。

In your case, technically it doesn't really matter which entity has the FK field ( logically , it may). 在您的情况下,从技术上讲 ,哪个实体具有FK字段( 逻辑上 ,它可能)并不重要。 I've used this model: 我用过这个模型:

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

With this mapping: 有了这个映射:

public class ReviewConfiguration : EntityTypeConfiguration<Review>
{
    public ReviewConfiguration()
    {
        // One-to-One Optional
        HasOptional(s => s.Payment)
            .WithOptionalDependent(s => s.Review)
            .Map(s => s.MapKey("PaymentId"));
    }
}

(So, apart from Payment.ReviewId , this is identical to the model + mapping in your question). (因此,除了Payment.ReviewId ,这与你问题中的模型+映射相同)。

Now I can do things like ... 现在我可以做......

db.Set<Review>().Add(new Review { Payment = new Payment() });
db.Set<Payment>().Add(new Payment { Review = new Review() });
db.SaveChanges();

... where db of course is a context. ...其中db当然是一个上下文。 The content of both tables now is: 这两个表的内容现在是:

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

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

And I can query the data bidirectionally like so: 我可以像这样双向查询数据:

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

or 要么

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

But instead of ReviewConfiguration , I can also use... 但是,我还可以使用...而不是ReviewConfiguration

public class PaymentConfiguration : EntityTypeConfiguration<Payment>
{
    public PaymentConfiguration()
    {
        // One-to-One Optional
        HasOptional(s => s.Review)
            .WithOptionalDependent(s => s.Payment)
            .Map(s => s.MapKey("ReviewId"));
    }
}

Now there will be an FK field ReviewId in table Payment , and the rest of the code works without changes. 现在,在表Payment中将有一个FK字段ReviewId ,其余代码无需更改即可运行。

You must have typos in your models (2 ReviewId fields in payment?). 您的模型中必须存在拼写错误(付款中有2个ReviewId字段?)。 Also, if you're going the fluent route don't put any relationship attributes in there to confuse matters. 此外,如果你走的是流畅的路线,不要在那里放置任何关系属性来混淆事情。 IAC, try something like this: 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);
    }
}

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

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