EF - 2:很多关系没有像预期的那样发展
本文关键字:关系 EF | 更新日期: 2023-09-27 18:02:56
我在Users
之间有Payments
。Payment
有一个FromUser
和一个ToUser
。我正在用以下代码测试实体关系:
var newPayment = new Payment() {
FromUserId = user1.UserId,
ToUserId = user2.UserId
};
db.Payments.Add(newPayment);
db.SaveChanges();
var tempPaymentId = user1.Payments.First().PaymentId;
newPayment = db.Payments.First(s => s.PaymentId == tempPaymentId);
Assert.AreEqual(newPayment.FromUserId, user1.UserId); // true
Assert.AreEqual(newPayment.ToUserId, user2.UserId); // true
Assert.AreEqual(user1.Payments.Count(), 1); // true
Assert.AreEqual(user2.Payments.Count(), 1); // false
我的问题是-为什么user2
没有任何Payments
?
类和流畅配置:
public class Payment {
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int PaymentId { get; set; }
[ForeignKey("FromUser")]
public int FromUserId { get; set; }
public User FromUser { get; set; }
[ForeignKey("ToUser")]
public int ToUserId { get; set; }
public User ToUser { get; set; }
}
public PaymentConfiguration() {
HasRequired(s => s.FromUser);
HasRequired(s => s.ToUser);
}
public UserConfiguration() {
// One-to-Many
HasMany(s => s.Payments);
}
这可能是由于许多原因,但是,首先,您混合了Data Annotations和Fluent API映射。为什么?我不确定它是否像预期的那样工作,但我确信它看起来不对。坚持使用一个(我推荐使用Fluent API)。其次,我认为,你应该有两个导航属性在User
Payments
。User.Payments
并不意味着什么,你想要用户支付的费用,还是通过一个导航属性支付给用户的费用?你只需要从一边映射。最后,您的模型和映射应该如下所示:
public class User
{
public int UserId { get; set; }
// Navigation properties
public virtual ICollection<Payment> PaymentsFromUser { get; set; }
public virtual ICollection<Payment> PaymentsToUser { get; set; }
}
public class UserConfiguration
: IEntityTypeConfiguration<User>
{
public UserConfiguration()
{
// Primary key
HasKey(m => m.UserId);
Property(m => m.PaymentId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
}
}
public class Payment
{
public int PaymentId { get; set; }
public int FromUserId { get; set; }
public int ToUserId { get; set; }
// Navigation properties
public virtual User FromUser { get; set; }
public virtual User ToUser { get; set; }
}
public class PaymentConfiguration
: IEntityTypeConfiguration<Payment>
{
public PaymentConfiguration()
{
// Primary key
HasKey(m => m.PaymentId);
Property(m => m.PaymentId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
// Relationship mappings
HasRequired(m => m.FromUser)
.WithMany(m => m.PaymentsFromUser)
.HasForeignKey(m => m.FromUserId)
.WillCascadeOnDelete(true);
HasRequired(m => m.ToUser)
.WithMany(m => m.PaymentsToUser)
.HasForeignKey(m => m.ToUserId)
.WillCascadeOnDelete(true);
}
}
注意: virtual
关键字用于Lazy loading
,如果不需要,可以跳过。
现在它应该按预期工作了。只要记住这样测试:
Assert.AreEqual(user1.PaymentsFromUser.Count(), 1);
Assert.AreEqual(user2.PaymentsToUser.Count(), 1);
请注意,我认为user1
和user2
都是由EntityFramework跟踪的,因此EF可以将用户与付款联系起来。