我正在关注这个问题:EF Code First - 1-to-1 Optional Relationship
我的关系设置如下:
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"));
}
}
我得到其中一个键有效,但另一个键从未映射为可选 FK:
我做错了什么?
我见过一些涉及创建空列表等的奇怪的 hacky 解决方案 - 不是我要找的。我在这里寻找合适的方法 - 它必须存在...对吗?
更新
我现在正在使用上面的内容 - 当我手头有付款并需要访问或删除评论时,我必须对 [伪 FK] ReviewId 进行另一次查找,这非常糟糕。
最佳答案
在任何一对一关联中,EF 只使用一个外键。当需要关联时,外键也将是依赖实体的主键,解释为here .
当关联是可选的时,两个实体应该能够独立存在。所以他们的主键不能是外键,因为 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"));
}
}
(因此,除了 Payment.ReviewId
之外,这与您问题中的模型 + 映射相同)。
现在我可以做...
db.Set<Review>().Add(new Review { Payment = new Payment() });
db.Set<Payment>().Add(new Payment { Review = new Review() });
db.SaveChanges();
... db
当然是上下文。现在两个表的内容是:
PaymentId
-----------
1
2
ReviewId PaymentId
----------- -----------
1 1
2 2
我可以像这样双向查询数据:
var data = db.Set<Review>().Include(r => r.Payment).ToList();
或
var data = db.Set<Payment>().Include(r => r.Review).ToList();
但是除了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"));
}
}
现在 Payment
表中将有一个 FK 字段 ReviewId
,其余代码无需更改即可工作。
关于.net - 一对一的可选关系,两端可选且两个 FK,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37040666/