EF - 2:很多关系没有像预期的那样发展

本文关键字:关系 EF | 更新日期: 2023-09-27 18:02:56

我在Users之间有PaymentsPayment有一个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);
}

EF - 2:很多关系没有像预期的那样发展

这可能是由于许多原因,但是,首先,您混合了Data AnnotationsFluent API映射。为什么?我不确定它是否像预期的那样工作,但我确信它看起来不对。坚持使用一个(我推荐使用Fluent API)。其次,我认为,你应该有两个导航属性在User PaymentsUser.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);

请注意,我认为user1user2都是由EntityFramework跟踪的,因此EF可以将用户与付款联系起来。