我关注这个问题: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上进行另一次查找,这完全很糟糕。
答案 0 :(得分:7)
在任何一对一关联中,EF仅使用一个外键。当需要关联时,外键也将是依赖实体的主键,如here所述。
当关联是可选的时,两个实体应该能够彼此独立地存在。所以他们的主键不能是外键,因为PK不能是可选的。这里需要一个额外的可空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();
但我可以使用...... {/ p>而不是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"));
}
}
现在表ReviewId
中将有一个FK字段Payment
,其余代码无需更改即可运行。
答案 1 :(得分:1)
您的模型中必须存在拼写错误(付款中有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);
}
}